I'm trying to write exercises for multimethods. Book readers will be working at the repl. Multimethods are stateful in a bad way, as shown below. Is there some sort of trick to using multimethods at the repl, or should I just give up on exercises using them?
;; Two types:
user=> (defn ship [name] (with-meta {:name name} {:type :ship}))
user=> (defn asteroid [name] (with-meta {:name name} {:type :asteroid}))
;; The dispatch function and defmulti
user=> (def classify-colliding-things
(fn [thing1 thing2]
[(type thing1) (type thing2)]))
user=> (defmulti collide classify-colliding-things)
;; Actually, since the arguments can come in any order, it'd be better to sort the types:
user=> (def classify-colliding-things
(fn [thing1 thing2]
(sort [(type thing1) (type thing2)])))
;; And let's redefine the multimethod to use the new comparison function.
user=> (defmulti collide classify-colliding-things)
;; OK, now we define the methods.
user=> (defmethod collide [:asteroid :ship]
[& things]
"collide asteroid to ship")
;;; And use them with great confidence:
user=> (collide (ship "Space Beagle") (asteroid "Malse"))
IllegalArgumentException No method in multimethod 'collide' for dispatch value: [:ship :asteroid] clojure.lang.MultiFn.getFn (MultiFn.java:121)
;;; The redefinition didn't take
-----
Brian Marick, Artisanal Labrador
Contract programming in Ruby and Clojure
Occasional consulting on Agile
Writing /Functional Programming for the Object-Oriented Programmer/:
https://leanpub.com/fp-oo