命名空间映射命名空间上的多方法分派

时间:2018-04-30 12:03:25

标签: clojure namespaces multimethod

是否可以根据命名空间的地图命名空间即#:<this-thing>{}进行调度?没有打印或检查关键前缀等黑客攻击?

我认为最后一个hacky是因为可以覆盖键前缀:

(:qux/bar #:qux{:bar :baz}); => :baz
(:foo/bar #:qux{:foo/bar :baz}); => :baz
(:qux/bar #:qux{:foo/bar :baz}); => nil

2 个答案:

答案 0 :(得分:3)

映射可能包含来自某个命名空间的所有限定关键字键,或者它可能包含来自多个命名空间的非限定键或限定键的混合。这是一个函数,用于从映射中的限定关键字键获取所有命名空间(作为关键字)的集合:

(defn key-namespaces
  "Returns set of all namespaces of keys in m."
  [m]
  (->> (keys m)
       (keep (comp keyword namespace))
       (set)))

现在,您可以在多方法中将其用作dispatch-fn

(defmulti do-thing key-namespaces)
(defmethod do-thing #{:foo} [m] (prn m))
(do-thing #:foo{:bar 1})
;; #:foo{:bar 1}
(foo {:bar/bar 1})
;; no multimethod found exception

您可以在该集合中指定多个名称空间前缀,也可以根据您的使用情况使用不同的dispatch-fn

答案 1 :(得分:1)

这是不可能的,因为这只是writer生成的地图的直观表示。如果地图中的所有键共享相同的命名空间,则必须自己进行检查。此外,最后一个示例将不会由编写者生成 - 它仅在all the keys share the same namespace时才会发出命名空间的地图文字。