clojure以编程方式命名空间映射键

时间:2017-05-01 15:54:20

标签: clojure namespaces clojurescript

我最近在clojure中了解了namespaced maps。 非常方便,我想知道以编程方式命名地图的惯用方法是什么?还有其他我不知道的语法吗?

  ;; works fine
  (def m #:prefix{:a 1 :b 2 :c 3})
  (:prefix/a m) ;; 1

  ;; how to programmatically prefix the map?
  (def m {:a 1 :b 2 :c 3})
  (prn #:prefix(:foo m))        ;; java.lang.RuntimeException: Unmatched delimiter: )

2 个答案:

答案 0 :(得分:5)

此功能可以满足您的需求:

(defn map->nsmap
  [m n]
  (reduce-kv (fn [acc k v]
               (let [new-kw (if (and (keyword? k)
                                     (not (qualified-keyword? k)))
                              (keyword (str n) (name k))
                              k) ]
                 (assoc acc new-kw v)))
             {} m))

您可以为它提供一个实际的命名空间对象:

(map->nsmap {:a 1 :b 2} *ns*)
=> #:user{:a 1, :b 2}

(map->nsmap {:a 1 :b 2} (create-ns 'my.new.ns))
=> #:my.new.ns{:a 1, :b 2}

或者为命名空间名称添加一个字符串:

(map->nsmap {:a 1 :b 2} "namespaces.are.great")
=> #:namespaces.are.great{:a 1, :b 2}

它只会改变非限定关键字的键,它与#:宏的行为相匹配:

(map->nsmap {:a 1, :foo/b 2, "dontalterme" 3, 4 42} "new-ns")
=> {:new-ns/a 1, :foo/b 2, "dontalterme" 3, 4 42}

答案 1 :(得分:0)

这是另一个灵感来自https://clojuredocs.org/clojure.walk/postwalk#example-542692d7c026201cdc327122

的例子
(defn map->nsmap
"Apply the string n to the supplied structure m as a namespace."
 [m n]
 (clojure.walk/postwalk
 (fn [x]
   (if (keyword? x)
     (keyword n (name x))
     x))
  m))

示例:

(map->nsmap  {:my-ns/a 1 :my-ns/b 2 :my-ns/c 3} "your-ns") 

=> #:your-ns{:a 1, :b 2, :c 3}