3

I can understand how this works:

(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

But by simply changing :Shape to :Shap, I stop understanding how this is being dispatched:

(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 on Eclipse with Counterclockwise plugin

m0skit0
  • 25,268
  • 11
  • 79
  • 127
  • I tried it in lein's REPL and it worked, must be an issue with CounterClockwise (I bet the user namespace wasn't reinitialized between both tests). – omiel Jul 05 '14 at 16:34
  • BTW, you must have a typo in your first example: either the `::B` keyword in the method definition shouldn't be namespaced or the `:B` in the call example should be. – omiel Jul 05 '14 at 16:35

1 Answers1

7

Multimethods don't like being redefined with a new dispatch function. This is a rather controversial feature, but it's the way things are. In order to change a multimethod's dispatch function, you must first def it to something which is not a multimethod (for example, to nil).

(defmulti area :Shape)

(def area nil)

(defmulti area :Shap)
amalloy
  • 89,153
  • 8
  • 140
  • 205