2014-09-12 3 views
6

Я читал «Clojure Обоснование» здесь:Что означает «Clojure поддерживает несколько таксономий» в отношении полиморфизма?

http://clojure.org/rationale 

В разделе Полиморфизм читаем:

Clojure multimethods decouple polymorphism from OO and types 

    Supports multiple taxonomies 
    Dispatches via static, dynamic or external properties, metadata, etc 

Что подразумевается под «поддерживает несколько таксономических» здесь? Я факт, что такое таксономия в этом случае? Спасибо

+2

В Java, например, у вас есть иерархия классов и должны использовать эти классы и интерфейсы в качестве основы для полиморфизма. С помощью нескольких методов Clojure вы можете создать произвольные иерархии/системы классификации (таксономии) в качестве основы полиморфизма. –

ответ

3

Clojure, как и многие другие функциональные языки, использует возможность бесплатного ввода текста для обеспечения простых способов реализации parametric polymorphism. Это в основном означает, что один метод может быть сконструирован таким образом, что ему не нужны типы значений, аргументы, которые он задает.

Возьмем, к примеру, метод concat. Он принимает любое количество аргументов различных форм и помещает их в единый список, как так:

user=> (concat [:a :b] nil [1 [2 3] 4]) 
(:a :b 1 [2 3] 4) 

Потому что один не нужно объявлять набор текста для аргументов, concat могут быть написаны таким образом, что вы можете предоставить аргумент любого типа (вектор, функция, ключевое слово, строка и т. д.), и он будет действовать на них аналогичным образом.

Clojure's multimethods позволяет поддерживать эту концепцию на объектах Java, которые могут иметь совершенно разные структуры (например, таксономии), используя метаданные или другие свойства, чтобы определить подходящий способ борьбы с данным аргументом. Смотрите следующий пример (взятый из defmulti):

(defmulti greeting 
    (fn[x] (x "language"))) 

(defmethod greeting "English" [params] 
    (str "Hello! " (params "id"))) 
(defmethod greeting "French" [params] 
    (str "Bonjour! " (params "id"))) 

=>(greeting {"id" "1", "language" "English"}) 
"Hello! 1" 
=>(greeting {"id" "2", "language" "French"}) 
"Bounjour! 2" 

Метод greeting возвращает значение "language" из карты, которая соответствует "English" или "French" DEFMETHOD который возвращает правильное соответствующее значение. Надеюсь, вы можете увидеть, как эта концепция потенциально может быть применена практически к любому типу данных или структуре объектов. Эта мощная идея полиморфизма - это то, что разработчики Clojure пытаются показать на странице обоснования.

+0

«... совершенно разные структуры (т. Е. Таксономии) ...» - это заявление смущает меня. Вы говорите, что их структура - их таксономия? Вы имели в виду, например, так что их таксономии могут быть одной структурой? Любое из этих чтений кажется странным для меня откровенно. Таксономия - это иерархия классификации, и я просто не могу разобрать утверждение с учетом этого определения. – noisesmith

5
user> (defmulti shade :color) 
nil 
user> (defmethod shade :black [_] "darkest of darks") 
#<MultiFn [email protected]> 
user> (defmethod shade :white [_] "all frequencies are reflected") 
#<MultiFn [email protected]> 
user> (defmulti movement :legs) 
#'user/movement 
user> (defmethod movement 2 [_] "walks on hind legs") 
#<MultiFn [email protected]> 
user> (defmethod movement 4 [_] "proceeds on all fours") 
#<MultiFn [email protected]> 
user> ((juxt movement shade) {:name "cat" :legs 4 :color :black}) 
["proceeds on all fours" "darkest of darks"] 

В приведенном выше коде созданы две системы организации - одна с точки зрения цвета, другая с точки зрения ног. Обе эти таксономии одинаково действительны, и один и тот же объект может попадать в разные места в зависимости от используемой таксономии.

Мультиметоды могут также использовать иерархии для отправки (см. derive и связанные функции), где каждая иерархия может сосуществовать параллельно (в отличие от унифицированного представления иерархии классов).

user> (derive ::manx ::cat) 
nil 
user> (defmulti favorite-treat :species) 
#'user/favorite-treat 
user> (defmethod favorite-treat ::cat [_] "Tuna") 
#<MultiFn [email protected]> 
user> (derive ::indoor ::domestic) 
nil 
user> (defmulti activity :tameness) 
#'user/activity 
user> (defmethod activity ::domestic [_] "window watching") 
#<MultiFn [email protected]> 
user> ((juxt favorite-treat activity) {:species ::manx :tameness ::indoor}) 
["Tuna" "window watching"] 

здесь же котенок является членом двух иерархий - один из одомашнивания, а другой генетики, и может быть его методы разрешаются либо в зависимости от обстоятельств.

Кроме того, даже установка ASID мультиметоды, отношения, созданные с помощью поддержки derive множественного наследования, в отличие от JVM класса иерархией Clojure строится на:

user> (derive ::foo ::bar) 
nil 
user> (derive ::foo ::baz) 
nil 
user> (derive ::quux ::foo) 
nil 
user> (isa? ::quux ::foo) 
true 
user> (isa? ::quux ::bar) 
true 
user> (isa? ::quux ::baz) 
true 
user> (isa? ::bar ::baz) 
false 
Смежные вопросы