Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macros 特殊形式和宏之间的实际区别是什么?_Macros_Clojure_Lisp_Scheme_Common Lisp - Fatal编程技术网

Macros 特殊形式和宏之间的实际区别是什么?

Macros 特殊形式和宏之间的实际区别是什么?,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-PC

特殊形式和宏之间有实际区别吗?它们有什么不同?

与特殊表单相比,宏表单可以进行宏扩展:

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

Lisp具有某些语言原语,它们构成了Lisp表单:

  • 文字数据:数字、字符串、结构
  • 函数调用,如
    (sin2.1)
    或类似
    ((lambda(ab)(+ab2))34)
  • 特殊运算符用于特殊形式。这些是基本的内置语言元素。请参见Common Lisp中的。这些需要在解释器和编译器中实现。CommonLisp无法让开发人员引入新的特殊操作符,也无法提供自己的特殊操作符版本。代码解析工具需要理解这些特殊操作符;在Lisp社区中,这些工具通常被称为“代码漫游器”。在定义通用Lisp标准的过程中,确保了该数字非常小,并且所有扩展都是通过新函数和新宏完成的
  • :宏是转换源代码的函数。转换将递归进行,直到源代码中没有宏。Common Lisp具有内置宏,允许用户编写新宏

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

这些术语并不是同义词,但它们也不是排他性的(此答案假设方案):

  • 特殊形式(在方案报告中也称为语法)是一种未根据函数应用的默认规则进行计算的表达式。(为了明确起见,默认规则是
    eval
    所有子表达式,然后
    apply
    将第一个子表达式的结果应用到其他子表达式的结果列表中。)
  • 宏系统是一种语言功能,允许在语言本身中定义新的特殊形式。宏是使用宏系统定义的特殊形式
所以您可以说“特殊形式”是一个与接口或语义相关的术语,而“宏”是一个与实现相关的术语。“特殊形式”表示“这些表达式使用特殊规则求值”,而“宏”表示“这里有一个用于计算某些表达式的特殊规则的实现。”

现在一件重要的事情是,大多数Scheme特殊形式可以从一个非常小的原语核心定义为宏:
lambda
if
和宏。一个只提供这些的最小方案实现仍然可以将其余的作为宏实现;最近的Scheme报告通过引用诸如“库语法”之类的特殊形式(可以用宏来定义)做出了区分。然而,在实践中,实际的Scheme系统通常实现一组更丰富的表单作为原语


从语义上讲,表达式唯一重要的是使用什么规则对其求值,而不是如何实现该规则。因此,从这个意义上讲,特殊形式是作为宏还是原语实现并不重要。但另一方面,Scheme系统的实现细节经常“泄漏”,因此您可能会发现自己关心它……

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

这是懒人的超短答案


您可以在任何时候编写自己的宏,尽管您不能在不重新编译clojure的情况下添加特殊表单

如果
if
也可以作为
lambda
上的宏实现
的可能副本。这不是非常有效,但知道这一点很简单。我觉得这个答案是最清楚的。由于它根据语义定义了
特殊形式
,也就是说,不依赖于实现细节。@amalloy,我对如何做到这一点很感兴趣,你手头有链接吗?@SimonLindgren我可能在这里夸大了这种情况,因为我认为你必须重新构建大量语言才能使用更多的lambda。但这是一篇关于Ruby中lambda演算的精彩博文,是Clojure的翻译。由此,您可以定义一个宏,让您“实际上”只使用lambda,同时仍然使用漂亮的
if
作为语法糖。如果您没有宏调试器,这是一个问题,但一些Lisp确实有。例如,Racket有一个你甚至可以从.Hi Matthias使用的。在陶艾岛,诺维格声称,
setf
是一种特殊形式。然而,它确实在扩大。例如:
(宏扩展)(setf测试4))
扩展到
(SETQ测试4)
书中可能有错误?我在这里也看不到
setf