Clojure let 绑定表单

Posted

技术标签:

【中文标题】Clojure let 绑定表单【英文标题】:Clojure let binding forms 【发布时间】:2014-06-19 21:33:25 【问题描述】:

我试图了解 let 绑定如何在地图方面以闭包方式工作。据我了解,let 后跟一个向量,其中第一项是我要绑定的符号,然后是我要绑定到的值。所以

(let [a 1 b 2] a) 

将给出 1 的值。

所以如果我声明地图如

(def people :firstName "John" :lastName "Doe")

我想绑定键 firstName 那么这将是简单“Hello Person”的正确形式

(let [personName (:firstName people)] (str "hello " personName))

这可行,但是在 Clojure 网站 http://clojure.org/special_forms#binding-forms 上,它们显示了另一种形式,也可以使用

(let [personName :firstName people] (str "hello " personName))

两个代码 sn-ps 都可以工作,我理解为什么第一个版本可以工作,但我对第二个版本的语法感到困惑。这只是语法糖还是重复的工作方式,并且比另一种更惯用?

【问题讨论】:

请参阅您链接到的文档中的地图绑定解构部分。 您的地图中没有键 :name 对不起,我把钥匙命名错了。 【参考方案1】:

最后一种形式是地图绑定解构。如果您想将多个变量绑定到同一张地图的不同元素,这是最有用的:

(let [firstName :firstName lastName :lastName address :address people]
    (str "hello " firstName " " lastName ", I see you live at " address))

如果你用前面的语法写出来,那就是:

(let [firstName (:firstName people) lastName (:lastName people) address (:address people)]
    (str "hello " firstName " " lastName ", I see you live at " address))

如您所见,这使您不必在每个绑定中重复 people。如果映射是计算的结果,它就不必将变量绑定到它,以便您可以重复它。

解构还允许您以类似于您正在访问的数据结构的格式布置绑定构造。这使得它更适合复杂的结构。

【讨论】:

user2766755,你可以对其他数据结构做类似的事情:(def x [5 10]) (let [[x1 x2] x] (* x1 x2)) => 50。有些人觉得映射绑定解构语法有点奇怪,因为键在它们限定的局部变量之后。 (例如,有这种感觉。)但是,“关键秒”语法总体上似乎更有用是有原因的。 Here 是对该问题的一次讨论。 更短的解构地图的方法是:(let [:keys [firstName lastName address] people] (println firstName lastName address))【参考方案2】:

只是说清楚(我希望不要太迂腐)......

(let [personName (:firstName people)] (str "hello " personName))

没有将密钥 :firstname 绑定到任何东西;您将标识符personName 绑定到关键字:firstname 作为函数 到映射people 的应用。

(let [personName :firstName people] (str "hello " personName))

您正在解构映射people,将标识符personName 绑定到它在键:firstname 处的值。


PS

这个奇迹是由let 表单调用的destructure 函数实现的。查看它的作用可能会有所帮助。例如,

(destructure '[personName :firstName people])
;[map__779
; people
; map__779
; (if
;  (clojure.core/seq? map__779)
;  (clojure.lang.PersistentHashMap/create (clojure.core/seq map__779))
;  map__779)
; personName
; (clojure.core/get map__779 :firstName)]

我接受了这个想法here。

【讨论】:

以上是关于Clojure let 绑定表单的主要内容,如果未能解决你的问题,请参考以下文章

let 绑定中的 Clojure 函数

在没有嵌套 let 的情况下在 Clojure 中绑定多个相关变量

Clojure:让作用域和函数返回值

Clojure 交换!在 let 绑定中的 map 函数内不起作用

Clojure let vs Common Lisp let

`let` 在 Clojure 中是如何实现的,它的开销是多少?