Clojure多方法区分地图和地图列表

Clojure多方法区分地图和地图列表,clojure,Clojure,我想写一个函数,可以处理一个特定的东西(由一个映射表示)或这些映射的列表 是否可以为此使用defmulti/defmethod?有人能给我举一个例子,说明如何编写测试函数作为映射或映射列表吗?您可以这样做: (defmulti foo type) (defmethod foo clojure.lang.IPersistentMap [m] (println "map")) (defmethod foo clojure.lang.Sequential [m] (println "seq

我想写一个函数,可以处理一个特定的东西(由一个映射表示)或这些映射的列表


是否可以为此使用defmulti/defmethod?有人能给我举一个例子,说明如何编写测试函数作为映射或映射列表吗?

您可以这样做:

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

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"))
在构建这样的案例时必须小心,以确保不会遇到满足两个案例的具体类型。如果是这样的话,将选择哪一个是任意的-使用
preferredmethod
定义首选项。(还请注意,尽管您可以使用协议执行与上述完全相同的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"))

请注意,有多个映射类—(类{})将是PersistentArrayMap,但大多数键/值对大于8的映射实际上将是PersistentHashMaps。@您是对的。将我的示例更新为更通用。