2012-02-22 99 views

回答

18

条款不是完全相同的,但它们不是唯一的或者(这个回答假设方案):

  • 一个特殊形式(也称为语法该计划的报告)是不根据函数应用程序的默认规则评估的表达式。 (默认的规则,只是明确的,是eval所有的子表达式,然后apply第一个到其他结果列表的结果。)
  • 宏系统是一个语言特性这允许在语言本身内定义新的特殊形式。 A 是使用宏系统定义的特殊形式。

所以,你可以说,“特殊形式”是属于接口语义的术语,而“宏”是属于实施的术语。 “特殊形式”意思是“这些表达式用特殊规则来评估”,而“宏”则意味着“这里是评估某些表达式的特殊规则的实现。“

现在一个重要的事情是,大多数方案的特殊形式可以从原语的一个非常小的核心被定义为宏:lambdaif和宏的最小方案的实现,只提供了这些仍然可以实现,其余为宏。最近的计划报告通过引用诸如可以用宏定义的“库语法”这样的特殊形式来进行区分,但是实际上,实际的计划系统通常实现一组更丰富的形式作为原语。对于表达而言,唯一重要的是用什么规则来评估它,而不是这条规则是如何实现的。所以从这个意义上说,一个特殊的表单是否被实现为一个宏或一个原语。但另一方面,一个Scheme系统的实现细节经常“泄漏”,所以你可能会发现自己正在关注它...

+1

你可以在'lambda'之上实现'if'作为宏。以及。这不是非常有效,但它是一个很好的知识。 – amalloy 2012-02-23 02:55:34

+0

我觉得这个答案是最清楚的。因为它根据其语义定义了“特殊形式” - 也就是说 - 不依赖于实现细节。 – 2012-02-23 15:18:12

+1

@amalloy,我感兴趣的是如何做到这一点,你有一个方便的链接? – 2013-02-04 13:35:16

4

相较于特殊形式,宏观形式可以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 
+0

嗨马蒂亚斯。在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

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具有内置的宏,并允许用户编写新的宏。

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

4

对我来说最实际的区别是在调试器中:宏不显示在调试器中;相反,宏的扩展中的(通常)不明确的代码显示在调试器中。调试这些代码是一个真正的痛苦,并且在开始依赖这些代码之前确保您的宏是坚如磐石的一个很好的理由。

+1

如果你没有一个宏调试器,这是一个问题,但是一些Lisp实际上是这样做的。例如,Racket有一个甚至可以从[REPL](http://docs.racket-lang.org/xrepl/index.html# \(xrepl._syntax \))中使用。 – 2012-02-24 03:37:23

2

懒惰的

超级简短的回答,您可以写自己的macroes任何你想要的时候,虽然你不能添加特殊形式无需重新编译的Clojure。

相关问题