Как написать вариативный метод defmulti/def в clojure

У меня есть группа defmulti/defmethod, которая принимает такие пары аргументов...

(defmulti foo "some explanation" (fn [arg1 arg2] (mapv class [arg1 arg2])))
(defmethod foo [N P] (->L 1 2 3))
(defmethod foo [L P] (->N 5))
(defmethod foo [P N] (->L 6 7 8))
 ...

Которые называются так, как вы могли бы ожидать.

(foo (->N 9) (->P 9))

Я хотел бы вызвать «foo» с более чем двумя аргументами. Я знаю, как это сделать с помощью функций, и я полагаю, что мог бы использовать некоторую функцию-оболочку, которая разбивает аргументы на пары, а затем объединяет результат (или просто использует «уменьшить»), но это кажется неправильным.

Тогда мой вопрос... Каков идиоматический способ определить вариативную многофункциональность в clojure?


person phreed    schedule 30.09.2014    source источник
comment
Точно так же вы делаете обычные функции вариативными — дайте функции отправки и defmethod телам вариативную подпись.   -  person Alex    schedule 01.10.2014
comment
Спасибо, я только что нашел это... stackoverflow.com/questions/10313657/   -  person phreed    schedule 01.10.2014


Ответы (1)


Нет ничего плохого в том, чтобы дать функции диспетчеризации defmulti и телам defmethod вариативные подписи, и это совершенно идиоматично:

(defmulti bar (fn [x & y] (class x)))
(defmethod bar String [x & y] (str "string: " (count y)))
(defmethod bar Number [x & y] (str "number: " (count y)))

(bar "x" 1 2 3) ;=> "string: 3"
(bar 1 2 3) ;=> "number: 2"
person Alex    schedule 30.09.2014
comment
Я использовал ваш ответ для создания образца в clojuredocs. clojuredocs.org/clojure.core/ - person phreed; 02.10.2014