【发布时间】:2012-03-12 21:33:26
【问题描述】:
特殊形式和宏之间有什么实际区别吗?它们有什么不同?
【问题讨论】:
标签: macros clojure lisp scheme common-lisp
特殊形式和宏之间有什么实际区别吗?它们有什么不同?
【问题讨论】:
标签: macros clojure lisp scheme common-lisp
与特殊形式相比,宏形式可以进行宏扩展:
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:lispworks.com/documentation/lw60/CLHS/Body/…
Lisp 具有某些语言原语,它们构成了 Lisp 形式:
(sin 2.1) 或((lambda (a b) (+ a b 2)) 3 4)
所以特殊形式和宏之间最重要的实际区别是:特殊运算符是内置的语法和语义。它们不能由开发人员编写。宏可以由开发者编写。
【讨论】:
这些术语不是完全同义的,但它们也不是排他性的(这个答案假设 Scheme):
eval 所有子表达式,然后 apply 第一个结果到其他结果列表。)所以你可以说“特殊形式”是一个属于接口或语义的术语,而“宏”是一个属于实现的术语。 “特殊形式”的意思是“这些表达式是用特殊的规则来计算的”,而“宏”的意思是“这是一个特殊规则的实现,用于计算某些表达式。”
现在重要的一点是,大多数 Scheme 特殊形式都可以定义为来自非常小的原语核心的宏:lambda、if 和宏。仅提供这些的最小 Scheme 实现仍然可以将其余部分实现为宏;最近的方案报告通过引用可以根据宏定义的“库语法”等特殊形式进行了区分。然而,在实践中,实际的 Scheme 系统通常会实现一组更丰富的表单作为原语。
从语义上讲,表达式唯一重要的是使用什么规则来评估它,而不是该规则是如何实现的。所以从这个意义上说,特殊形式是实现为宏还是原语并不重要。但另一方面,Scheme 系统的实现细节经常“泄露”,所以你可能会发现自己很在意它......
【讨论】:
if 实现为lambda 之上的宏。它的效率不是很高,但知道它是一件好事。
special-form——也就是说——不依赖于实现细节。
if 作为语法糖。
对我来说,最实际的区别在于调试器:宏不会出现在调试器中;相反,宏扩展中的(通常)晦涩的代码显示在调试器中。调试此类代码确实很痛苦,并且有充分的理由在开始依赖宏之前确保它们坚如磐石。
【讨论】:
懒人的超级简短答案
您可以随时编写自己的宏,但如果不重新编译 clojure,则无法添加特殊形式。
【讨论】: