如何在Clojure中将lambda实现为一个名为“lambda”的函数?

时间:2010-03-23 04:02:15

标签: lambda clojure macros

我希望能够在Clojure中使用常见的Lisp语法定义lambdas。例如:

(lambda (myarg)
  (some-functions-that-refer-to myarg))

这需要与:

相同
#(some-functions-that-refer-to %)

在我的情况下,我知道我总是会有一个arg,所以也许这简化了事情。 (但它可以被称为任何东西 - “myarg”或其他什么。)

我怀疑一个可行的解决方案是“(defmacro lambda ......”。如果是这样,我不确定最好的方法。如何干净地将arg名称翻译为%?以及如何结束正确的功能?

或者,是否有一个比编写我自己的宏更简单的解决方案,实际上重新实现了Clojure的...... lambda?

1 个答案:

答案 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表单以及dofor等根据我的理解,这背后的基本原理是列表用于函数调用或宏调用,而向量用于非调用的事物(例如,要绑定的符号列表)。可以说,它使得以可视方式扫描代码比列出所有方式更容易。 Clojure不是Common Lisp,如果你试图强迫它,你会感到痛苦。

如果你真的,真的想这样做,只是说你做了:

binding

除了其他方面,这不允许您在函数上放置文档字符串或元数据。我认为你不想在真正的Clojure程序中使用它。