defmethod抓住所有

时间:2012-02-25 01:20:42

标签: clojure multimethod

我有一个专门研究两个参数的多方法:

(defmulti get-tag-type (fn [type tag] [type tag]))

拥有该类型允许我将不同的defmethod调用分组:

(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)

但是,有时候,我想要一个catch all或默认为其中一个组,如果没有其他组匹配则会被调用:

(defmethod get-tag-type [::dog :default] ::mutt)

但是,除非tag实际上是:default,否则这不起作用。

实现这一目标的好方法是什么?

3 个答案:

答案 0 :(得分:7)

您的调度功能需要知道哪些映射已经定义,以便它可以决定何时采用默认值。 methods函数会将这些映射返回给您。

(defmulti get-tag-type (fn [type tag] 
                         (let [mlist (methods get-tag-type)]
                           (if-let [d (get mlist [type tag])] 
                             [type tag]
                             [type :default]))))

答案 1 :(得分:7)

如果没有其他方法匹配,则多方法支持使用(可配置)值:default标识的回退方法。

在您的情况下,您只需添加:

(defmethod get-tag-type :default [type tag]
  (do special behaviour here ...))

根据您的示例,可能值得注意的是您可以使用Clojure关键字建立层次结构,而多方法调度可以理解这些层次结构:http://clojure.org/multimethods

答案 2 :(得分:0)

您可以将defmulti更改为:

(defmulti get-tag-type (fn [type tag] 
                         (if (= type ::dog)
                             ::dog
                             [type tag])))

然后写下你的方法:

(defmethod get-tag-type ::dog ::mutt)