我希望能够在Clojure中使用常见的Lisp语法定义lambdas。例如:
(lambda (myarg)
(some-functions-that-refer-to myarg))
这需要与:
相同#(some-functions-that-refer-to %)
在我的情况下,我知道我总是会有一个arg,所以也许这简化了事情。 (但它可以被称为任何东西 - “myarg”或其他什么。)
我怀疑一个可行的解决方案是“(defmacro lambda ......”。如果是这样,我不确定最好的方法。如何干净地将arg名称翻译为%?以及如何结束正确的功能?
或者,是否有一个比编写我自己的宏更简单的解决方案,实际上重新实现了Clojure的...... lambda?
答案 0 :(得分:26)
#(foo %)
只是(fn [arg] (foo arg))
的读者简写。没有理由编写扩展为#(...)
的宏。无论如何,%
构造中的所有#(...)
都会被扩展为gensyms。
user> `#(foo % %1 %2)
(fn* [user/p1__1877 user/p2__1878]
(user/foo user/p1__1877 user/p1__1877 user/p2__1878))
如果您正在编写一个扩展为构建匿名函数的宏,您可以自己将它们扩展为fn
表单。在您的情况下,您应该直接使用fn
并跳过宏。 fn
是Clojure的lambda
。
在这种情况下,(fn [] ...)
和(lambda () ...)
之间的差异是“fn”的类型比“lambda”短,fn
为其绑定采用向量,而{{1拿一个列表。如果您正在使用Clojure,那么您最终必须习惯这一点,因为向量总是用于绑定集合,所有lambda
表单以及do
和for
等根据我的理解,这背后的基本原理是列表用于函数调用或宏调用,而向量用于非调用的事物(例如,要绑定的符号列表)。可以说,它使得以可视方式扫描代码比列出所有方式更容易。 Clojure不是Common Lisp,如果你试图强迫它,你会感到痛苦。
如果你真的,真的想这样做,只是说你做了:
binding
除了其他方面,这不允许您在函数上放置文档字符串或元数据。我认为你不想在真正的Clojure程序中使用它。