3

我想要类似{: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) })
4

2 回答 2

10

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

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

map这只是取未评估的符号,keyword将它们向下传递以获得关键字序列,然后zipmap是原始符号的键序列。由于它是一个宏,因此在此之后将评估结果形式,产生关键字到值(符号所指的值)的映射。

所以如果你去做:

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

...它将返回:

{:x 1 y 2 :z 3}

这是你想要的?

于 2012-07-29T00:25:42.340 回答
3

固定点:虽然您正在寻求的解决方案会起作用,但尚不清楚为什么您“要避免两次键入每个变量的名称”。如果这是“个人偏好”,那么这看起来像是对宏工具的滥用,因为与使用 {:x 1 :y 2 :z 3} 或 (hash-map :xx : yx :zx)。您似乎购买了太少的便利来换取代码的复杂性。

宏可以使您的代码更难维护(其他人可能不理解它们),引入符号捕获之类的复杂性(您的代码可能会做的不仅仅是简单的哈希映射创建)并且不能像更高的那样使用/传递-订单函数(除非你包装它们)。

摘自“Joy Of Clojure”(第 8.8 节):“在掌握宏观的道路上,您可以学习的最重要的技能是识别何时避免使用它们的能力。一般的答案当然是无论何时,只要你可以。”

于 2012-07-30T20:41:48.013 回答