I have a multimethod that specializes on two parameters:
(defmulti get-tag-type (fn [type tag] [type tag]))
Having the type allows me to group the different defmethod calls into sets:
(defmethod get-tag-type [::cat 0] [type tag] ::tiger)
(defmethod get-tag-type [::cat 1] [type tag] ::lion)
(defmethod get-tag-type [::cat 2] [type tag] ::jaguar)
(defmethod get-tag-type [::dog 0] [type tag] ::poodle)
(defmethod get-tag-type [::dog 1] [type tag] ::australian-shepherd)
(defmethod get-tag-type [::dog 2] [type tag] ::labrador-retriever)
However, sometimes, I want a catch all or default for one of the groups, which would be called if none of the others matched:
(defmethod get-tag-type [::dog :default] ::mutt)
However, this doesn't work unless tag
is actually :default
.
What is a good way to accomplish this?
Multimethods support a fallback method, identified by using the (configurable) value :default
, if none of the other methods match.
In your case, you'd simply add:
(defmethod get-tag-type :default [type tag]
(do special behaviour here ...))
Given your example, it might be worth noting that you can establish hierarchies using Clojure keywords, and multimethod dispatch understands those hierarchies: http://clojure.org/multimethods
Your dispatch function needs to know which mappings are already defined so that it can decide when to resort to a default. The methods
function will return those mappings to you.
(defmulti get-tag-type (fn [type tag]
(let [mlist (methods get-tag-type)]
(if-let [d (get mlist [type tag])]
[type tag]
[type :default]))))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With