如何使用名称作为键从一组绑定创建一个映射?

时间:2012-07-28 23:38:34

标签: clojure

我想要类似于{:keys [...]}构造的反转:

(let [x 1 y 2 z 3] (create-map x y z))

...应该返回{:x 1 :y 2 :z 3}

换句话说,我想避免在{:x x :y y :z z}中两次输入每个变量的名称。

我想要这个功能的一个例子:

(defn create-some-service-handle [user-id password api-key] 
    { :api-key api-key 
      :user-id user-id 
      :connection (obtain-connection user-id password) })

2 个答案:

答案 0 :(得分:6)

如果您正在寻找能够准确定位于create-map的位置的东西,那么您将需要一个宏,因为您需要将这些符号取消评估。这将是一个非常简单的宏:

(defmacro create-map
  [& syms]
  (zipmap (map keyword syms) syms))

这只是将未评估的符号map s keyword向下移动以获取一系列关键字,然后zipmap是带有原始符号的键序列。由于它是一个宏,在此之后将评估结果表单,产生关键字到值的映射(符号引用的值)。

所以,如果你去做:

(let [x 1 y 2 z 3] (create-map x y z))

......它将返回:

{:x 1 y 2 :z 3}

这是你在找什么?

答案 1 :(得分:1)

Fixpoint:虽然您正在寻找的解决方案可行,但目前还不清楚为什么您“要避免两次输入每个变量的名称”。如果这是一个“个人偏好”,那么这看起来像滥用宏设施,因为使用宏获得的便利性与使用{:x 1:y 2:z 3}或(hash-map:xx: yx:zx)。您似乎在购买太少的便利以换取代码复杂性。

宏可以使您的代码不易维护(其他人可能无法理解),引入符号捕获等复杂功能(您的代码可能不仅仅是创建哈希映射)而且不能使用/传递像高阶函数(除非你包装它们)。

摘自“欢乐的Clojure”(第8.8节): “你在宏观掌握的道路上可以学到的最重要的技能是能够识别何时避免使用它们。当然,一般的答案是随时随地都可以。”