【问题标题】:This map destructuring isn't working quite how I'd expect. What am I doing wrong?这个地图解构并不像我期望的那样工作。我究竟做错了什么?
【发布时间】:2015-02-18 20:29:08
【问题描述】:

作为一个例子,希望能比我用语言更好地说明事情:

(let [{:keys [a b c] :or {a 1 b 2 c 3} :as m} {}]
  (println a b c) ; => works as expected, output is: 1 2 3
  (println m) ; => this doesn't work, output is: {}
)

我希望第二个 println 的输出是包含默认值的映射,就好像被合并推到那里一样(即 {:a 1 :b 2 :c 3})。

相反,在 m 被绑定之后,看起来 vars 正在被召唤和​​ or'd。为什么 :as 不受 : 或 :keys 的影响?

我的心智模型有什么问题?我应该如何看待这个?

编辑:
我想出了它是如何工作的,就像我在上面展示的那样(尽管感谢链接)。从那以后,我也通读了 clojure.core/destructure 的源代码,现在确切地知道它在做什么。我的问题真的是“为什么?”

在 Clojure 中,事情以它们的方式运行似乎总是有原因的。他们在这里做什么?

很抱歉,问题是“解构如何与 :as 和 :or 一起工作”。

【问题讨论】:

    标签: clojure


    【解决方案1】:

    我不是有钱人,所以显然我没有选择它的工作方式,但我可以想到当前行为比您预期的行为更好的几个原因。

    1. 它更快。 Clojure 的许多低级核心功能一直在您的程序中使用,为了获得可接受的性能,它们针对速度而不是优雅进行了优化。当然,如果这是一个正确性的问题,那就另当别论了,但是:as 有两种听起来合理的行为方式,所以选择更快的方式似乎是一个好计划。至于为什么它更快,我认为这很明显,但是:我们已经有一个指向原始地图的指针,我们可以重用它。要使用“修改后的”地图,我们必须使用一堆 assoc 调用来构建它。

    2. 如果:as不给你原始对象,你怎么可能得到原始对象?你不能,真的,对吧?而如果:as 将原始对象归还给您,您可以根据需要轻松构建修改后的版本。因此,一种行为会为您留下更多选择。

    【讨论】:

    • 啊!第二点完全让我忘记了。回想起来,它不应该。谢谢!
    【解决方案2】:

    根据Special Forms:as:or对于init-expr来说都是独立的:

    此外,可选地,绑定形式中的:as 键后跟符号将导致该符号绑定到整个 init-expr。也可选地,绑定表单中的:or 键后跟 另一个映射 可以用于为部分或所有键提供默认值如果它们在 init-expr 中找不到

    【讨论】:

      【解决方案3】:

      正如您所发现的,解构中的:or 键不会影响:as:as 将捕获原始输入,无论是否应用默认值或通过 & 等封装剩余元素。

      引用the docs on clojure.org

      还可以选择在绑定形式中使用 :or 键,后跟另一个 map 可用于为部分或全部键提供默认值 如果在 init-expr 中找不到它们

      ...

      最后,也是可选的,:as 后跟一个符号会导致 要绑定到整个 init-expr 的符号

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-17
        • 1970-01-01
        • 2013-08-06
        • 1970-01-01
        相关资源
        最近更新 更多