特殊形式和宏之间有什么实际区别?

时间:2012-02-22 14:33:27

标签: macros clojure lisp scheme common-lisp

特殊表格和宏之间是否存在实际差异?他们有什么不同?

5 个答案:

答案 0 :(得分:19)

这些术语不完全是同义词,但它们也不是排他性的(这个答案假定为Scheme):

  • 特殊表单(在Scheme Reports中也称为语法)是一个未根据函数应用程序的默认规则进行评估的表达式。 (默认规则,只是为了明确,是eval所有子表达式,然后apply第一个的结果到其他子结果的列表。)
  • 宏系统是一种语言功能,允许在语言本身内定义新的特殊表单。 是使用宏系统定义的特殊形式。

所以你可以说“特殊形式”是一个与接口语义相关的术语,而“宏”是与实现相关的术语。 “特殊形式”表示“这些表达式使用特殊规则进行评估”,而“宏”表示“这里是评估某些表达式的特殊规则的实现。”

现在一个重要的事情是大多数Scheme特殊形式可以从一个非常小的原始核心定义为宏:lambdaif和宏。仅提供这些的最小Scheme实现仍然可以将其余部分实现为宏;最近的Scheme Reports通过引用可以用宏定义的“库语法”这样的特殊形式来区分。然而,在实践中,实际的Scheme系统通常将更丰富的形式集实现为原语。

从语义上讲,对表达式唯一重要的是使用什么规则来评估它,而不是如何实现该规则。因此,从这个意义上说,将特殊表单实现为宏还是原语并不重要。但另一方面,Scheme系统的实现细节经常“泄漏”,所以你可能会发现自己关心它......

答案 1 :(得分:11)

Lisp有一些语言原语,构成了Lisp形式:

  • 文字数据:数字,字符串,结构......
  • 函数调用,例如(sin 2.1)或类似((lambda (a b) (+ a b 2)) 3 4)
  • 特殊运营商以特殊形式使用。这些是原始的内置语言元素。请参阅Common Lisp中的Special Operators。这些需要在解释器和编译器中实现。 Common Lisp无法让开发人员引入新的特殊运算符或提供您自己的版本。代码解析工具需要了解这些特殊的运算符;这些工具通常被称为“代码助行器”。在Lisp社区。在Common Lisp标准的定义过程中,确保数字非常小,并且所有扩展都是通过新功能和新宏完成的。
  • :宏是正在转换源代码的函数。转换将以递归方式发生,直到源代码中没有宏。 Common Lisp具有内置宏,允许用户编写新的宏。

因此,特殊形式和宏之间最重要的实际区别是:特殊运算符是内置语法和语义。它们不能由开发人员编写。宏可以由开发人员编写。

答案 2 :(得分:4)

与特殊形式相比,宏形式可以进行宏扩展:

CL-USER(1): (macroexpand '(with-slots (x y z)
                              foo
                            (format t "~&X = ~A" x)))

(LET ((#:G925 FOO))
  (DECLARE (IGNORABLE #:G925))
  (DECLARE (SB-PCL::%VARIABLE-REBINDING #:G925 FOO))
  #:G925
  (SYMBOL-MACROLET ((X (SLOT-VALUE #:G925 'X))
                    (Y (SLOT-VALUE #:G925 'Y))
                    (Z (SLOT-VALUE #:G925 'Z)))
    (FORMAT T "~&X = ~A" X)))
T

答案 3 :(得分:4)

对我来说,最实际的区别在于调试器:宏不会出现在调试器中;相反,宏的扩展中的(通常)模糊代码显示在调试器中。调试这样的代码真是太痛苦了,并且在开始依赖它们之前确保宏是坚如磐石的一个很好的理由。

答案 4 :(得分:2)

懒惰的超短答案

您可以随时编写自己的宏,但无法添加特殊表单而无需重新编译clojure。