【问题标题】:Clojure: Why let binding doesnt work like for binding?Clojure:虽然 let 绑定不像绑定那样工作?
【发布时间】: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 绑定的工作原理吗? 谢谢!

【问题讨论】:

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

标签: clojure


【解决方案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]]
    

    【讨论】:

    • 你能帮我展示一些关于你的答案的例子吗?文档示例有时过于复杂
    • 添加示例。
    猜你喜欢
    • 2014-03-21
    • 2014-06-19
    • 2013-05-31
    • 2015-11-20
    • 2012-06-07
    • 2012-04-11
    • 2014-01-23
    • 1970-01-01
    • 2014-11-30
    相关资源
    最近更新 更多