Clojure 全力以赴

Clojure 全力以赴,clojure,multimethod,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 t

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

(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或default,如果其他组都不匹配,就会调用该组:

(defmethod get-tag-type [::dog :default] ::mutt)
但是,除非
标记
实际上是
:默认值
,否则这不起作用


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

您可以将defmulti更改为:

(defmulti get-tag-type (fn [type tag] 
                         (if (= type ::dog)
                             ::dog
                             [type tag])))
然后像这样写你的方法:

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

分派函数需要知道已经定义了哪些映射,以便决定何时使用默认值。
方法
函数将向您返回这些映射

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

多方法支持回退方法,如果其他方法都不匹配,则使用(可配置)值
:default

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

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

在您的示例中,可能值得注意的是,您可以使用Clojure关键字建立层次结构,并且multimethod dispatch可以理解这些层次结构:

我不希望defmulti知道将使用它的defmethods。不幸的是,对于不同类型的值,我需要不同的默认行为,我相信每个多重方法只能定义一个
:默认值