Понимание диспетчеризации мультиметодов

#clojure #multimethod

#clojure #мультиметод

Вопрос:

Я могу понять, как это работает:

 (defmulti area :Shape)
(defmethod area :B [x] (println "Rect"))
(defmethod area :C [x] (println "Circle"))
(defmethod area :default [x] (do (println "Unknown") (:Shape x)))
(area {:Shape :B})
=> Rect
nil
(area {:Shape :Bb})
=> Unknown
:Bb
  

Но, просто изменив :Shape на :Shap , я перестаю понимать, как это отправляется:

 (defmulti area :Shap)
(defmethod area :B [x] (println "Rect"))
(defmethod area :C [x] (println "Circle"))
(defmethod area :default [x] (do (println "Unknown") (:Shap x)))
(area {:Shap :B})
=> Unknown
:B
(area {:Shap :C})
=> Unknown
:C
  

Clojure 1.5.1 в Eclipse с плагином против часовой стрелки

Комментарии:

1. Я попробовал это в lein’s REPL, и это сработало, должно быть, проблема с CounterClockwise (бьюсь об заклад, пространство имен пользователя не было повторно инициализировано между обоими тестами).

2. Кстати, у вас, должно быть, опечатка в вашем первом примере: либо ::B ключевое слово в определении метода не должно иметь пространства имен, либо :B в примере вызова должно быть.

Ответ №1:

Мультиметодам не нравится, когда их переопределяют с помощью новой функции диспетчеризации. Это довольно спорная функция, но так уж обстоят дела. Чтобы изменить функцию диспетчеризации мультиметода, вы должны сначала определить ее на что-то, что не является мультиметодом (например, на nil).

 (defmulti area :Shape)

(def area nil)

(defmulti area :Shap)