在Clojure中构建匿名函数的映射

Nik*_*yrh 5 clojure

我只是在学习语言而且我有一个简单的问题.为什么这样做(构造{:key "value"}):

(#(assoc {} :key %) "value")
Run Code Online (Sandbox Code Playgroud)

但这不是:

(#({:key %}) "value")
ArityException Wrong number of args (0) passed to: PersistentArrayMap  clojure.lang.AFn.throwArity (AFn.java:429)
Run Code Online (Sandbox Code Playgroud)

在Python上,后一种语法完全有效:

> (lambda v: {'key': v})('value')
{'key': 'value'}
Run Code Online (Sandbox Code Playgroud)

编辑:感谢很好的答案,显然我需要停止思考#lambdaPython相同.

Nat*_*vis 6

#(f %)被读者扩展为(fn [%] (f %).同样,#({:key %})扩展到(fn [%] ({:key %}).python相当于它lambda v: {'key': v}(),它与Clojure版本具有完全相同的问题.

你正在寻找的东西相当于(fn [v] {:key v}).如果你真的想使用#(...)符号,你可以使用#(do {:key %}).

顺便说一句,我个人从不使用#(...).我认为这很难(例如这个证据的例子),并且只比同等fn形式更紧凑.然后还有#(...)形式无法嵌套的限制.


nta*_*lbs 5

这就是#()读者的局限性。fn会正常工作。

user=> ((fn [x] {:key x}) "value")
{:key "value"}
Run Code Online (Sandbox Code Playgroud)

请看文档Anonymous function literal (#())

  • 根据文档,`#(… )` 将被翻译成 `(fn [args] (… ))`。所以`#({:key %})` 将被翻译成`(fn [x] ({:key x}))`。这会导致错误,因为 `{:key x}` 处于函数位置并且没有意义。 (2认同)