Clojure程序员如何使用宏?

时间:2011-09-29 07:33:08

标签: clojure

我的理解是Clojure's homoiconicity存在,以便更容易编写宏。

基于this stackoverflow thread,除了不使用高阶函数的DSL之外,看起来很少使用宏。

有人可以分享一些关于如何在现实生活中使用宏的例子吗?

1 个答案:

答案 0 :(得分:17)

homoiconicity使编写Clojure宏非常容易,这是正确的。基本上,它们使您能够编写构建所需代码的代码,利用Lisp的“代码是数据”理念。

同性语言中的宏也非常强大。我找到了一个有趣的示例演示文稿implement a LINQ-like query syntax in just three lines of Clojure

通常,Clojure宏可能有很多原因:

  • 控制结构 - 可以使用永远无法表示为的宏来创建某些控制结构。例如,你不能把if写成一个函数,因为如果它是一个函数,那么它必须评估所有三个参数,而使用宏你可以使它只评估两个(条件值和 false

  • 编译时间优化 - 有时您希望根据已知或可在编译时计算的常量来优化代码。例如,您可以创建一个“日志记录”功能,仅在代码以调试模式编译时才记录,但在生产应用程序中创建零开销。

  • 代码生成/样板消除 - 如果您需要生成许多具有相似结构的非常相似的代码,那么您可以使用宏从几个参数自动生成这些代码。如果你讨厌样板,那么宏就是你的朋友。

  • 创建新语法 - 如果您认为需要特定的语法片段(可能封装了常见模式),那么您可以创建一个宏来实现它。例如,某些DSL可以通过其他语法进行简化。

  • 使用全新的语义创建一种新语言(对SK-Logic的信用!)理论上你甚至可以使用宏来创建一种新的语言,这将有效地编译你的新语言语言进入Clojure。新的langauge甚至不必像Lisp一样:它可以解析和编译任意字符串,例如。

一个重要的建议是只在您需要时使用宏并且功能不起作用。大多数问题都可以通过功能来解决。除了宏对于简单情况而言过度杀戮之外,函数还有一些内在优势:它们更灵活,可以存储在数据结构中,可以作为参数传递给更高阶函数,更容易让人们理解等等。