Clojure multimethod on class OR keyword
Suppose I have this multimethod
(defmulti m (fn [v] [(:type v)]))
(defmethod m [Object] [k] (prn "Object"))
(defmethod m [:mykwd] [k] (prn "mykwd"))
When I call it with subclass of Object
, it correctly dispatches to the first implementation:
(m {:type String})
"Object"
With the :mykwd
it also works as expected:
(m {:type :mykwd})
"mykwd"
But when I provide another keyword I get an exception:
(m {:type :anotherkwd})
#<CompilerException java.lang.IllegalArgumentException: No method in multimethod 'm'
for dispatch value: [:anotherkwd] (NO_SOURCE_FILE:0)>
How exactly does this dispatch work?
Is it possible to preserve this behavior for class inheritance and still have a "default" implementation that catches all keywords?
EDIT This example is simplistic, but I need it to work with binary functions. My real nee开发者_如何转开发d is below. I don't see how I could apply :default
to it.
(defmulti m (fn [arg mp] [(class arg) (:type mp)]))
Then I'm looking for a way to define it for the case when arg
is nil
and (:type mp)
is anything. This works when value for :type
is a class, but not for any keyword:
(defmethod m [nil Object] [arg mp] (prn "Whatever"))
There is a default:
(defmethod m :default [x] :oops)
Reference:
Check http://clojure.org/multimethods at the bottom of the page.
Try replacing your :type
dispatch with a custom function that returns a default value when :type
is nil
. Same for class
. Then you can dispatch on a vector of keywords. Add the keywords to a hierarchy if you need inherited behavior.
精彩评论