Полиморфизм в Clojure - PullRequest
       25

Полиморфизм в Clojure

2 голосов
/ 18 июля 2010

Предположим, у меня есть куча структур данных Clojure одного типа, например, тип объекта, определенный defrecord.

Каков наилучший способ получить полиморфное поведение в этих структурах?

Было бы хорошей практикой встроить функцию в структуру, чтобы я мог сделать что-то вроде:

((:my-method my-object) param1 param2)

Или есть лучший способ?

Ответы [ 2 ]

5 голосов
/ 18 июля 2010

Вы можете использовать мультиметоды для отправки,

(derive ::subtype ::type)

, затем вы можете отправлять на основе типа

(defmulti my-method
  (fn [type] ((meta type) :type)))

(defmethod my-method ::subtype []
  ;;stuff...
 )

. Вам необходимо добавить: type к метаданным объектов при его создании,

(with-meta [1 2 3] {:type ::subtype})

или я не пробовал этого, но поскольку протоколы и записи создают Java-классы за кулисами, которые вы отправляете на основе этого имени.

2 голосов
/ 18 июля 2010

Если я понимаю ваш вопрос, протоколы - это то, что вы хотите использовать.

user=> (defprotocol P (foo [p x]))
P
user=> (defrecord R [a b] P (foo [_ x] [a b x]))
user.R
user=> (defrecord S [a b] P (foo [_ x] [x b a]))
user.S
user=> (def r (R. 1 2))
#'user/r
user=> (def s (S. 1 2))
#'user/s
user=> (foo r 3)
[1 2 3]
user=> (foo s 3)
[3 2 1]

В приведенном выше примере R и S реализуют функцию foo, определенную протоколом P, но каждый из них делает это по-своему. Когда вызывается функция foo, она отправляет тип первого аргумента.

...