这种地图解构并不像我期望的那样有效。我究竟做错了什么?

时间:2015-02-18 20:29:08

标签: clojure

作为一个例子,希望能够比言语更好地陈述事情:

(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的输出是包含默认值的地图,好像在那里通过merge推送(即{:a 1:b 2:c 3})。

相反,在绑定m之后看起来像变形和变形。为什么:因为不受以下因素的影响:或者像:键呢?

我的心理模型出了什么问题?我该怎么看?

修改
我想出它是如何工作的,因为我认为我已经在上面展示了(尽管感谢链接)。我也读过clojure.core / destructure的来源,现在确切知道它在做什么。我的问题真的是'为什么?'

在Clojure中,似乎总有一种理由可以像他们一样工作。他们在这里干什么?

我很抱歉这个问题出现了'解构如何与:as和:或'。

3 个答案:

答案 0 :(得分:4)

我不富有,所以很明显我没有选择这是如何运作的,但我可以想到一些原因,目前的行为比你预期的行为更好。

  1. 速度更快。很多Clojure的低级核心功能在程序中始终使用,并且为了获得可接受的性能,它们的优化速度优于优雅。当然,如果这是一个正确的问题,它将是一个不同的故事,但这里有两种合理的方式:as表现,所以选择更快的方式似乎是一个好的计划。至于为什么它更快,我认为这是显而易见的,但是:我们已经有一个指向原始地图的指针,我们可以重复使用它。要使用"修改过的" map,我们必须使用一堆assoc调用来构建它。

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

答案 1 :(得分:3)

根据Special Forms:as:orinit-expr方面都是独立的:

  

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

答案 2 :(得分:3)

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

引用the docs on clojure.org

  

同样可选地,a:或绑定表单中的键后跟另一个键   map可用于为某些或所有键提供默认值   如果在init-expr中找不到它们

...

  

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