:keys 解构的逆过程:从序列构造映射

fr1*_*13d 2 clojure

我在 Clojure 中写得越多,就越会遇到以下类型的模式:

(defn mapkeys [foo bar baz]
   {:foo foo, :bar bar, :baz baz})
Run Code Online (Sandbox Code Playgroud)

从某种意义上说,这看起来像是解构的逆过程。

(let [{:keys [foo bar baz]}] ... )
Run Code Online (Sandbox Code Playgroud)

会实现。

Clojure 中是否有一种“内置”方式来实现与上述类似的东西mapkeys(将名称映射到关键字=> 值)——也许是针对任意长度的名称列表?

ama*_*loy 7

没有内置这样的东西,因为它不需要。与相当复杂的解构不同,在 Clojure 中构造映射非常简单,因此为普通库留下了奇特的方法。比如我很早以前写过的flatland.useful.map/keyed,反映了地图解构的三种模式:

(let [transforms {:keys keyword
                  :strs str
                  :syms identity}]
  (defmacro keyed
      "Create a map in which, for each symbol S in vars, (keyword S) is a
  key mapping to the value of S in the current scope. If passed an optional
  :strs or :syms first argument, use strings or symbols as the keys instead."
    ([vars] `(keyed :keys ~vars))
    ([key-type vars]
       (let [transform (comp (partial list `quote)
                             (transforms key-type))]
         (into {} (map (juxt transform identity) vars))))))
Run Code Online (Sandbox Code Playgroud)

但是如果你只关心关键字,而不需要一个文档字符串,它可能会更短:

(defmacro keyed [names]
  (into {}
        (for [n names]
          [(keyword n) n])))
Run Code Online (Sandbox Code Playgroud)