example doesn’t have a hierarchy complex enough to introduce multiple
“inheritance.” Such relationships arise frequently when you have
multimethods dealing with interfaces.
Let’s say we want a
function that can execute anything vaguely runnable (like
(defmulti run "Executes the computation." class) (defmethod run Runnable [x] (.run x)) (defmethod run java.util.concurrent.Callable [x] (.call x))
Let’s test it on a function:
(run #(println "hello!")) ;= #<IllegalArgumentException java.lang.IllegalArgumentException: ;= Multiple methods in multimethod 'run' match dispatch value: ;= class user$fn__1422 -> interface java.util.concurrent.Callable and ;= interface java.lang.Runnable, and neither is preferred>
The exception is pretty self-explanatory: since Clojure functions
Callable, the multimethod doesn’t know which
implementation to pick and hints that one should be
Preferences are expressed through the
prefer-method function. This function expects three arguments: the
multimethod considered and two dispatch values, the
first being the one that should be preferred over the second:
(prefer-method run java.util.concurrent.Callable Runnable) ;= #<MultiFn clojure.lang.MultiFn@6dc98c1b> (run #(println "hello!")) ;= hello! ;= nil
Now the multimethod knows which implementation to pick, to prefer, and runs without problem.
This preferences mechanism ...