我想编写一个可以处理特定事物(由地图表示)或这些地图列表的函数。
是否可以使用defmulti / defmethod?有人能指出我如何编写测试函数作为地图或地图列表的例子吗?
答案 0 :(得分:5)
Multimethods将自动使用类层次结构,因此您只需打开类型:
(defmulti process class)
(defmethod process clojure.lang.IPersistentMap [m]
(println "got map"))
(defmethod process clojure.lang.Sequential [s]
(println "got sequential"))
(defmethod process :default [o]
(println "got something else"))
在构建这样的案例时必须小心,以确保不会遇到满足两种情况的具体类型。如果是这样,那将是任意选择 - 使用prefer-method
来定义首选项。 (另请注意,尽管您可以使用协议执行与上述完全相同的impl,但是没有相同的方法可以使用协议选择首选结果。)
或者您可以在检测您关注的案例时任意调整您的调度方法:
(defmulti process
(fn [o]
(cond
(map? o) :map
(sequential? o) :sequential
:else (class o))))
(defmethod process :map [m]
(println "got map"))
(defmethod process :sequential [s]
(println "got sequential"))
(defmethod process :default [o]
(println "got something else"))
答案 1 :(得分:2)
你可以这样做:
(defmulti foo type)
(defmethod foo clojure.lang.IPersistentMap [m]
(println "map"))
(defmethod foo clojure.lang.Sequential [m]
(println "sequential"))
但是,使用具有条件的单个函数可能更清晰,例如
(if (map? m)
(deal with the map)
(deal with each map, e.g. by recursing over each element))