特殊形式和宏之间有什么实际区别?它们的不同之处在哪里?
特殊形式和宏之间有什么实际区别?它们的不同之处在哪里?
这些术语并不完全同义,但它们也不是互斥的(假定本答案中的 Scheme):
eval
所有子表达式,然后将第一个子表达式的结果应用到其他子表达式的结果列表上。)因此可以说,“特殊形式”是与接口或语义有关的术语,而“宏”是与实现有关的术语。“特殊形式”意味着“这些表达式使用特殊规则进行计算”,而“宏”则意味着“这是一种计算某些表达式的特殊规则的实现方法。”
现在一个重要的事情是,大多数 Scheme 特殊形式都可以从一个非常小的原始操作集合定义为宏:lambda
、if
和宏。仅提供这些操作的最小 Scheme 实现仍然可以将其余部分实现为宏。最近的 Scheme 报告通过称这些特殊形式为“库语法”,并且可以用宏来定义以此作出了区分。但是,实际上,实用的 Scheme 系统通常实现了更丰富的表单作为原语。
从语义上讲,关于一个表达式的唯一重要的事情就是使用什么规则来计算它,而不是如何实现这个规则。因此,在这个意义上,特殊形式是作为宏还是作为原语实现并不重要。但另一方面,Scheme 系统的实现细节通常会泄漏,所以您可能会关心它……
lambda
的基础上实现 if
宏。这并不是非常高效,但了解这一点还是很不错的。 - amalloyspecial-form
,而不依赖于具体实现细节。 - Pedro RoloLisp有一些语言原语,它们构成了Lisp形式:
(sin 2.1)
或者((lambda (a b) (+ a b 2)) 3 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
setf
是一个特殊形式。然而,它可以进行宏展开。例如:(macroexpand '(setf test 4))
展开为 (SETQ TEST 4)
。也许书中有错误?我在这里也没有看到setf
:http://www.lispworks.com/documentation/lw60/CLHS/Body/03_ababa.htm#clspecialops - anonymous对我来说,最实用的区别在于调试器:宏不会出现在调试器中;相反,通常是宏展开后的晦涩代码出现在调试器中。调试这样的代码真的很麻烦,这也是确保宏坚如磐石之前要开始依赖它们的一个很好的理由。
懒人的超级简短回答:
您可以随时编写自己的宏,但是如果要添加特殊形式,则需要重新编译Clojure。