S4M*_*S4M 33 macros lambda clojure
我理解宏 - >在clojure中应用了为给定参数提供的所有函数.但是,它似乎不适用于匿名函数(在clojure 1.3.0上).例如:
user> (-> 4 inc inc dec)
5
Run Code Online (Sandbox Code Playgroud)
但:
user> (-> 4 #(+ % 1) #(- % 1) #(+ % 1))
Run Code Online (Sandbox Code Playgroud)
返回错误:
clojure.lang.Symbol cannot be cast to clojure.lang.IPersistentVector
[Thrown class java.lang.ClassCastException]
Run Code Online (Sandbox Code Playgroud)
如果有人知道解决方法会有所帮助.谢谢!
Ank*_*kur 41
您可以在Clojure宏中使用匿名函数.你遇到了问题,因为你遗漏了一些括号.:)您的示例在下面编辑.
(-> 4 (#(+ % 1)) (#(- % 1)) (#(+ % 1)))
Run Code Online (Sandbox Code Playgroud)
and*_*oke 29
(这是基于我在评论中发布的问题的答案).
的->宏接受每个参数,使其成为一个列表中,如果必要的(在应用"原始"功能,以无参数-转换myfunc到(myfunc)),然后插入的第一个参数->为在每个这些列表中的第二个参数.
因此(-> foo myfunc)变得(-> foo (myfunc))变得(myfunc foo)大致.
这些都在文档中->描述.
匿名函数的问题在于它们是由读者宏生成的,如此处所述(向下滚动).这意味着将#(...)其转换(在正常的宏扩展之前)(fn [...] ...).这很好,但是,关键的是,已经是一个清单.
所以宏认为匿名函数已经被应用,实际上它正在遇到一个函数定义(两个都是列表).并添加"额外"的parens - 如上面在另一个答案中所述 - 将匿名函数应用于无args.
这种不直观的行为的原因是宏所使用的dwim(做什么意思,不是dwim-witted,虽然......)启发式->,添加了允许你提供"裸"功能而不是要求通过将它们包含在列表中来将它们应用于无args 只是一种启发式方法 - 它只是测试列表 - 并且被读取器宏创建的函数定义所混淆.
[我的脾气暴躁,->实施得很差,应该拒绝所有"裸"功能,而只是接受功能应用; 然后它会显得更加一致.如果没有,那么至少文档可以更清楚,解释将事物放入列表背后的激励语义.
您的具体案例可以简单地使用以下方法解决:
(-> 4 (+ 1) (- 1) (+ 1))
Run Code Online (Sandbox Code Playgroud)
其中线程优先宏->负责将上一步的结果作为第一个参数插入“当前”函数中。
造成混乱的原因是它->不是一个函数而是一个宏,并且在这种情况下参数的处理方式非常不同,正如其他答案所解释的那样。
| 归档时间: |
|
| 查看次数: |
4083 次 |
| 最近记录: |