Clojure:虽然 let 绑定不像绑定那样工作?

Posted

技术标签:

【中文标题】Clojure:虽然 let 绑定不像绑定那样工作?【英文标题】:Clojure: Why let binding doesnt work like for binding? 【发布时间】:2018-08-27 08:37:32 【问题描述】:

所以,我有一个带钥匙的clojure.lang.PersistentArrayMap,里面还有另一个clojure.lang.PersistentArrayMap,比如:

:foo :bar "bar"

当我将for 与绑定一起使用时:

(for [[key value] :foo :bar "bar"] do-something)

它工作正常,但是当我尝试使用let 时,它不起作用......

(let [[key value] :foo :bar "bar"] do-something)

有人可以帮助我了解 let 绑定的工作原理吗? 谢谢!

【问题讨论】:

因为到目前为止这两个答案都没有明确警告它:默认情况下地图没有排序或排序。它们以插入顺序排列的条目很少,因此您的示例可以工作;但请确保您的地图只有一个用于该用例的条目。 【参考方案1】:

以下是您的数据示例:

(forv [[key value] :foo :bar "bar"] ...)
  key   => :foo
  value => :bar "bar"


(let [[key value] (first (seq :foo :bar "bar"))]  ...)
  key   => :foo
  value => :bar "bar"

您需要first 从序列中仅获取一个MapEntry

请注意,如果您只需要第一个,则实际上并不需要 seq,因为 first 在其参数上内部调用 seq

(let [[key value] (first :foo :bar "bar")]      ; same result

【讨论】:

【参考方案2】:

使用for,您可以从所有MapEntrys 中创建一个序列(我们现在称它们为key-vals)。 for 是列表理解,而不是 for 循环,因此您正在创建一个列表(更具体的惰性序列),从绑定到输入上的连续值。 在let 中,您不会绑定到连续的值,而是绑定到一个值,除非您使用解构,在这种解构中您可以从某个序列中同时提取多个值。

使用let,您只能将第一个和第二个键值绑定到keyvalue,但这不受支持,因为映射没有明确的顺序。

但是使用seq,您可以从地图中获得两个键值:

(let [[a b] (seq :a 1 :b 2)] [a b])
;;=> [[:a 1] [:b 2]]

【讨论】:

你能帮我展示一些关于你的答案的例子吗?文档示例有时过于复杂 添加示例。

以上是关于Clojure:虽然 let 绑定不像绑定那样工作?的主要内容,如果未能解决你的问题,请参考以下文章

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

let 绑定中的 Clojure 函数

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

Clojure let vs Common Lisp let

在绑定向量中注释 Clojure

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