特殊形式和宏之间是否存在实际差异?它们有什么不同?特殊形式和宏之间的实际区别是什么?
回答
条款不是完全相同的,但它们不是唯一的或者(这个回答假设方案):
- 一个特殊形式(也称为语法该计划的报告)是不根据函数应用程序的默认规则评估的表达式。 (默认的规则,只是明确的,是
eval
所有的子表达式,然后apply
第一个到其他结果列表的结果。) - 宏系统是一个语言特性这允许在语言本身内定义新的特殊形式。 A 宏是使用宏系统定义的特殊形式。
所以,你可以说,“特殊形式”是属于接口或语义的术语,而“宏”是属于实施的术语。 “特殊形式”意思是“这些表达式用特殊规则来评估”,而“宏”则意味着“这里是评估某些表达式的特殊规则的实现。“
现在一个重要的事情是,大多数方案的特殊形式可以从原语的一个非常小的核心被定义为宏:lambda
,if
和宏的最小方案的实现,只提供了这些仍然可以实现,其余为宏。最近的计划报告通过引用诸如可以用宏定义的“库语法”这样的特殊形式来进行区分,但是实际上,实际的计划系统通常实现一组更丰富的形式作为原语。对于表达而言,唯一重要的是用什么规则来评估它,而不是这条规则是如何实现的。所以从这个意义上说,一个特殊的表单是否被实现为一个宏或一个原语。但另一方面,一个Scheme系统的实现细节经常“泄漏”,所以你可能会发现自己正在关注它...
你可以在'lambda'之上实现'if'作为宏。以及。这不是非常有效,但它是一个很好的知识。 – amalloy 2012-02-23 02:55:34
我觉得这个答案是最清楚的。因为它根据其语义定义了“特殊形式” - 也就是说 - 不依赖于实现细节。 – 2012-02-23 15:18:12
@amalloy,我感兴趣的是如何做到这一点,你有一个方便的链接? – 2013-02-04 13:35:16
相较于特殊形式,宏观形式可以macroexpanded:
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
嗨马蒂亚斯。在tAoAI中,Norvig声称''setf'是一种特殊的形式。但它做了宏观展开。例如:'(macroexpand'(setf test 4))'扩展到'(SETQ TEST 4)'也许这本书有错误?我在这里没有看到'setf':http://www.lispworks.com/documentation/lw60/CLHS/Body/03_ababa.htm#clspecialops – tsikov 2016-07-10 17:15:39
Lisp有一定的语言基本,从而弥补了Lisp的形式:
- 文字数据:数字,字符串,结构...
- 函数调用,像
(sin 2.1)
或类似((lambda (a b) (+ a b 2)) 3 4)
- 特殊运营商用于特殊形式。这些是原始的内置语言元素。请参阅Common Lisp中的Special Operators。这些需要在解释器和编译器中实施。 Common Lisp为开发人员提供了无法引入新的特殊运算符或提供您自己的版本的方法。代码解析工具需要理解这些特殊的操作符;这些工具通常在Lisp社区中被称为“代码助手”。在Common Lisp标准定义期间,确保数字非常小,并且所有扩展都是通过新函数和新宏完成的。
- 宏:宏是转换源代码的函数。该转换将递归发生,直到源代码中没有剩下宏。 Common Lisp具有内置的宏,并允许用户编写新的宏。
所以特殊形式和宏之间最重要的实际区别是:特殊的运算符是内置的语法和语义。它们不能由开发人员编写。宏可以由开发人员编写。
对我来说最实际的区别是在调试器中:宏不显示在调试器中;相反,宏的扩展中的(通常)不明确的代码显示在调试器中。调试这些代码是一个真正的痛苦,并且在开始依赖这些代码之前确保您的宏是坚如磐石的一个很好的理由。
如果你没有一个宏调试器,这是一个问题,但是一些Lisp实际上是这样做的。例如,Racket有一个甚至可以从[REPL](http://docs.racket-lang.org/xrepl/index.html# \(xrepl._syntax \))中使用。 – 2012-02-24 03:37:23
懒惰的
超级简短的回答,您可以写自己的macroes任何你想要的时候,虽然你不能添加特殊形式无需重新编译的Clojure。
- 1. Clojure:如何实现特殊形式,函数和宏的区别
- 2. Response.Write和<%= %>之间的实际区别是什么?
- 3. `_.defaults`和`_.extend`之间的实际区别是什么?
- 4. while(true)和for(;;)之间的实际区别是什么?
- 5. typedef和宏之间有什么区别?
- 6. ++和:haskell之间的区别是什么?
- 7. $(())和expr之间的区别是什么?
- 8. $(...)和`...`之间的区别是什么
- 9. [undefined]和[,]之间的区别是什么?
- 10. Atlassian SDK中atlas-run和atlas-run-standalone之间的实际区别是什么?
- 11. 命令窗口和立即窗口之间的实际区别是什么?
- 12. 在MySQL中`REPLACE`和`INSERT ... ON DUPLICATE KEY UPDATE`之间的实际区别是什么?
- 13. PHP中“关联”和“索引”数组之间的实际区别是什么?
- 14. clojure的特殊形式是什么?
- 15. 使用TPL和异步模式之间的实际区别
- 16. Highland.js,Kefir.js和Rx.js之间的区别特征是什么?
- 17. 区别:%% a和%variable%变量之间的区别是什么?
- 18. DDD:实体和值对象之间的区别是什么?
- 19. NSString与NSMutablestring之间区别的实际例子可能是什么样的?
- 20. VirtualizationStackPanel中VirtualizationMode属性的Recycling/Standard之间的实际区别是什么?
- 21. 所有这些Reactive Observable扩展之间的实际区别是什么?
- 22. 正则表达式中(。*)和(。*?)之间的区别是什么?
- 23. 语法和s表达式之间的区别是什么
- 24. GOF和GRASP设计模式之间的区别是什么
- 25. r +和w +模式之间的确切区别是什么?
- 26. 加载项和宏之间有什么区别?
- 27. MVC和MVVM之间的区别和相似之处是什么?
- 28. TVF/UDF之间的区别是什么
- 29. [EmailPasswordAuthProvider,EmailAuthProvider]之间的区别是什么
- 30. SI和DI寄存器的实际区别是什么?
可能重复[可以安全地忽略宏和内置之间的区别?](http://stackoverflow.com/questions/5120780/can-one-safely-ignore-the-difference-between-一个宏和一个内置的) – amalloy 2012-02-22 18:41:50