Ответ 1
Это прекрасно. Существует интерфейс "пользователь" и "тип" интерфейса библиотеки. Они могут быть одинаковыми, но они не должны.
Интерфейс пользователя находится в вашем случае which-colour
. Интерфейс "type" which-colour-mm
(ok, не совсем, но только ради аргумента). Пользователь вашей библиотеки не должен знать о мультиметоде.
С другой стороны, кому-то, предлагающему новый цвет - скажем :purple
, не нужно заботиться о многостраничном шаблоне. Это обрабатывается для него в which-colour
.
Это совершенно правильный дизайн!
Но, конечно же, есть ценник: предположим, что у вас есть цвет, который имеет еще более перманентный способ сделать что-то... Теперь вы заблокированы в возможно более медленном интерфейсе.
Прояснить это немного: предположим, что у вас есть интерфейс коллекции. Вы предоставляете функцию - conj
- которая позволяет пользователю добавлять элементы в коллекцию. Он выполняется следующим образом:
(defn conj
[coll & elements]
(reduce conj1 coll elements))
conj1
- это интерфейс типа (например, мультиметод или функция протокола): он добавляет один элемент в коллекцию. Поэтому кто-то, поставляющий новый тип коллекции, должен реализовать простой случай добавления одного аргумента. Автоматически новый тип также будет поддерживать добавление нескольких элементов.
Но теперь предположим, что у вас есть тип коллекции, который позволяет быстрее добавлять несколько элементов, чем просто добавлять друг за другом. Эта возможность не может быть использована сейчас.
Итак, вы делаете функцию multimethod/protocol самой функцией conj
. Теперь коллекция может использовать более быстрый способ. Но каждая реализация должна обеспечивать шаблонные элементы с несколькими элементами.
Это компромисс и ваше решение. Существует не правильный путь (tm). Оба могут считаться идиоматическими. (Хотя я лично постараюсь пойти с первым как можно чаще.)
YMMV.
Изменить: пример методов многозначности без кодирования в значении отправки.
(defmulti which-colour-mm (fn [m & args] (:colour m)))
(defmethod which-colour-mm :blue
([m] (print m))
([m f] (f m)))