Clojure中的多种方法,多态性,大开关

时间:2012-06-09 05:39:14

标签: clojure

我已经在很多Clojure代码中读取了模式(defmulti multi (fn [t] (cond (seq? t) :seq (map? t) :map (vec? t) :vec ...,它基本上是一个开关(如果我添加一个类型,我必须添加一个新子句)但更详细。有没有办法说(defmethod seq, (defmethod vec (defmethod map..等?这一定是很常见的事情。我知道可以手动定义层次结构,但是对于常见的Clojure类型,如sequence,vector,map ......,是否必须为每个在类型上调度的程序定义?请告诉我,我错过了这一点!

编辑:好吧我以为我可以说(defmulti mymulti type)然后(defmethod clojure.lang.PeristantSomething...等等,但是这很笨拙,因为它引用了java类,但我想引用一些'类型'的质量,比如它是否是顺序或关联

2 个答案:

答案 0 :(得分:3)

在类型上调度适用于此:

user> (import '[clojure.lang Associative Sequential])
user> (defmulti foo type)
#'user/foo

user> (defmethod foo Associative [x] :map)
#<MultiFn clojure.lang.MultiFn@7e69a380>

user> (foo {:x 1})
:map
user> (foo ())
; fails, a list is not associative

user> (defmethod foo Sequential [x] :seq)
#<MultiFn clojure.lang.MultiFn@7e69a380>
user> (foo ())
:seq
user> (foo [])
; fails, a vector is both sequential and associative

user> (prefer-method foo Sequential Associative)
#<MultiFn clojure.lang.MultiFn@7e69a380>
user> (foo [])
:seq

请注意,Sequential和Associative都是接口而不是具体类。

答案 1 :(得分:0)

选择调度函数是类型或类。