写道:维基百科关于宏的页面实际上根本没有关于它的历史。我添加了一些内容,包括>;对科尔贝克和克林格的引用。=C2=A0如果有人想让它变得更好(或纠正我对FEXPR的可怕猜测),请看一看:>;>;http://en.wikipedia.org/wiki/Macro_%28computer_science%29#Lisp_.2F_S-expression_macros``The最早的Lisp宏采用FEXPR的形式,这是一种类似函数的运算符,其输入不是参数计算的值,而是参数的语法形式,其输出是语法片段,将用来代替FEXPR的使用。';';FEXPR的参数绝对是语法形式,而不是`read';;返回的源代码的文字列表结构。FEXPR的‘output’用作调用FEXPR的表达式的返回值。差别很细微,但很关键。这取决于LISP I的实现细节。LISP I不是简单的语言定义的实现。它是一种“元循环”语言定义的实现。在具有元循环成分的语言中,我们可以将函数划分为两类:“正常”函数和“水平交叉”函数。在LISP I实现中,名称可以绑定到EXPR或SUBR,这只是一个一级过程(区别很简单,EXPR是通过递归计算实现的过程,而SUBR是通过在底层平台(IBM704汇编)中直接执行实现的过程)。SUBR可以是原始代码,也可以是编译后的代码块。)。但也有类似的跨级版本,称为FEXPR和FSUBR。FEXPR是通过递归求值实现的跨层过程,FSUBR是通过直接执行实现的跨层过程,但是FEXPR和FSUBR不是通过物化和反射在程序上工作的元句法运算符,而是依赖于EVAL的元循环定义的元实现运算符(即,FEXPR或FSUBR运行在元EVAL的语义层,而不是EVAL)。McCarthy等人并没有忽视这一区别。FEXPR是围绕这样一个事实“设计”的,即该语言有一个通过递归下降列表结构实现的元循环定义。大多数(如果不是全部)鼓动重新考虑FEXPR的人都不理解这一区别。宏是在语法级别执行重写的程序,它是从它所操作的程序的具体表示中抽象出来的。另一方面,FEXPR是一个故意“不”从具体表示中抽象出来的程序。在后来Lisp中,FEXPR被DEFMACRO取代,DEFMACRO是一种允许程序员指定在程序运行之前应用的源到源转换的系统。FEXPR(和FSUBR)实际上并没有被替换。FEXPR和FSUBR从未打算作为源-源转换。宏工具被添加为一个独立的、不相关的功能。FEXPR的问题在于它们太强大了,并且对实现施加了太多约束。研究发现,FEXPR的某些惯用用法是“安全的”(具有明确的、直观的语义),而另一些用法则是“不安全的”(具有模糊的语义,依赖于亚循环不动点(YIKS!)的存在。)。一个人不能用“不安全的FEXPR”进行有效的编程,所以他们很快就失宠了。‘Safe';FEXPR原来是FEXPR的子集,可以理解为源-源翻译。由于宏提供了同样的功能而没有随之而来的问题,它们很快就成为元程序的首选方式。有了FEXPR,亚循环就不再必要了,EVAL也不再需要对列表结构进行操作。另一种看待它的方式是这样的:一种语言的外指语义有一个函数`Big-E&39;将‘表达式’映射到‘值’。如果我们愿意,我们可以定义一个函数Big-P(用于解析),该函数将`列表结构‘映射到’表达式‘。如果我们愿意,我们可以定义一个将`列表结构映射到`表达式’的函数Big-P(用于解析)。LISP I定义Big-E[[]]=3D Apply(Big-E[[Car(Big-P^-1[[]])]],map(lambda(Arg)Big-P^-1[[eval Arg]])(Cdr(Big-P^-1[[]])(或类似的东西)。重点在于,Big-E的语义定义是通过代码和列表结构之间的同构来定义的,并且与之有着千丝万缕的联系。FEXPR操作同构(讨厌)两侧的对象,因此不能将Big-P和Big-P^-1从语义中分离出来。然而,宏只在一侧操作对象,允许将Big-P作为句法转换进行分解和隐藏。这大大简化了Big-E的定义(本质上,它允许我们在简单的Scott域上定义Big-E,而不是在反射域上定义Big-E)。--=20~JRM