这个地图解构并没有像我期望的那样工作。我究竟做错了什么?

This map destructuring isn't working quite how I'd expect. What am I doing wrong?

举个例子,希望能比我用文字表达得更好:

(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})。

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

我的思维模式有什么问题?我应该怎么看这个?

编辑:
我弄清楚了它是如何工作的,正如我在上面所展示的那样(尽管仍然感谢您提供的链接)。我也已经通读了 clojure.core/destructure 的源代码,现在确切地知道它在做什么。我的问题确实是 'Why?'

在 Clojure 中,似乎总是有一个原因让事情以它们的方式工作。他们在这里干什么?

很抱歉这个问题是 'how does destructuring work with :as and :or'。

根据 Special Forms:as:or 都独立于 init-expr:

In addition, and optionally, an :as key in the binding form followed by a symbol will cause that symbol to be bound to the entire init-expr. Also optionally, an :or key in the binding form followed by another map may be used to supply default values for some or all of the keys if they are not found in the init-expr

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

引用the docs on clojure.org

Also optionally, an :or key in the binding form followed by another map may be used to supply default values for some or all of the keys if they are not found in the init-expr

...

Finally, also optional, :as followed by a symbol will cause that symbol to be bound to the entire init-expr

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

  1. 速度更快。许多 Clo​​jure 的低级核心功能在您的程序中 一直被使用 ,并且它们针对速度而不是优雅进行了优化,以获得可接受的性能。当然,如果这是正确性问题,那就另当别论了,但是 :as 有两种听起来合理的行为方式,因此选择较快的方式似乎是一个不错的计划。至于为什么它更快,我认为这是显而易见的,但是:我们已经有了一个指向原始地图的指针,我们可以重用它。要使用 "modified" 地图,我们必须用一堆关联调用来构建它。

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