lambda表达式宏或标记是否在公共Lisp中?

lambda表达式宏或标记是否在公共Lisp中?,lambda,common-lisp,read-eval-print-loop,markers,lisp-macros,Lambda,Common Lisp,Read Eval Print Loop,Markers,Lisp Macros,我试图通过《CommonLisp:符号计算的温和介绍》一书来学习CommonLisp。此外,我正在使用SBCL、Emacs和Slime 在第7章中,作者就lambda表达式提出以下建议: 这让我很困惑,因为SBCL的REPL返回: CL-USER> #'lambda #<CLOSURE (:MACRO LAMBDA) {1000D736DB}> 请注意,append等“普通”函数的行为不同: CL-USER> #'append #<FUNCTION APPEND

我试图通过《CommonLisp:符号计算的温和介绍》一书来学习CommonLisp。此外,我正在使用SBCL、Emacs和Slime

在第7章中,作者就
lambda表达式
提出以下建议:

这让我很困惑,因为SBCL的REPL返回:

CL-USER> #'lambda
#<CLOSURE (:MACRO LAMBDA) {1000D736DB}>
请注意,
append
等“普通”函数的行为不同:

CL-USER> #'append
#<FUNCTION APPEND>
CL-USER>#'append
#
这篇文章似乎略微触及了lambda表达式的非单一性质。然而,它没有提到任何关于标记的内容


我错过了lambda表达式的本质吗?

思考这一点的一种方式是认识到,在CL中获得词汇上明显的函数值的唯一方法是特殊运算符
function
:如果你想在当前词汇环境中获得与
foo
相关的函数,你必须说
(函数foo)

比如说。因此,
function
是一个特殊的操作符,可以让您查看函数名称空间中的内容
函数
有一些语法上的糖分,即
#'
,就像
引用
一样(下面我不使用这个)。你可以把函数应用程序
(fxy)
想象成类似于
((函数f)xy)
,其中
是一种神奇的东西,它不会像那样被替换掉

但您也需要匿名函数,并且,您也可以使用
函数
,其参数是lambda表达式:

lambda表达式。一种列表,在某些上下文中可以用来代替函数名,通过直接描述函数的行为来表示函数,而不是通过引用已建立函数的名称来间接表示函数;它的名字来源于它的第一个元素是符号lambda

因此,匿名函数被表示为
(函数(lambda(…)…)
。如果愿意,您可以将
(lambda(…)…)
视为函数的“名称”。(我认为人们不喜欢这个,因为它干扰了匿名函数的概念,但很明显,有一组可数的函数“名称”,形式为
(lambda(…)…)
,我认为你甚至可以列举这个集合(这样做会像列举有理数一样繁琐)

由于函数应用程序中的函数位置已在函数名称空间中解释,
((lambda(…)…)
表示匿名函数应用程序:它与
(funcall(function)(lambda(…)…)…)
大致相同(请再次参阅)

这就是20世纪80年代CL的情况

还有一些我不确定的历史混乱:我记得它发生过,但我不记得顺序。首先,在Lisp-1中,你不需要任何
函数
的东西:表单
car
表示获得cons的car的函数,你不需要说
(function car)
。类似地,
(lambda(…)…)
表示一个函数。除此之外,还有另一个建议的Lisp标准,它是/是ISLisp,可能是。尽管ISLisp不是Lisp-1,但它确实有一个表示函数的形式
(lambda(…)

人们希望CL能够与ISLisp兼容,这意味着
(lambda(…)…)
应该表示一个函数。每个人实际做的是秘密添加一个定义,如:

(defmacro lambda (args &body forms)
  `(function (lambda ,args ,@forms)))
但是,关键的是,你不能在CL中移植,因为
lambda
CL:lambda
,你不允许在CL包中重新定义东西。人们无论如何都这么做了,但结果是他们的程序不可移植,并且经常需要用特殊的魔法来解锁和重新锁定
CL

这个问题的解决方案是语言必须提供这样一个宏。在CLtL1定义的语言和最终标准之间的某个时候发生了这种情况,所以现在
lambda
有一个宏定义,其扩展是(或多或少:实现可能被允许做特殊的事情)明显的扩展:

(lambda (x) x)
 -> #'(lambda (x) x)
因此,在现代CL中:

  • lambda
    开头的列表表示形式类似于
    (function(lambda(…)…)
    的函数,也表示形式的函数位置,例如
    ((lambda(x)x)1)
  • lambda
    被定义为一个宏,它可以扩展到
    (函数(lambda(…))
    ,从而更易于使用

注意:我认为,您使用的实现可以执行宏的功能,但您不应依赖于此:

在函数形式出现的词法环境中,对不表示函数的函数名使用函数是错误的。具体而言,在表示宏或特殊形式的符号上使用函数是错误的。出于性能原因,实现可以选择不发出此错误的信号,但实现是出于安全考虑禁止将错误信号的失败定义为有用的行为


你应该真正使用
宏函数
,它会告诉你某个东西是否有宏定义。

思考这一点的一种方式是认识到,在CL中获得词汇上明显的函数值的唯一方法是特殊运算符
函数
:如果你想获得与在当前词汇环境中,您必须说
(函数foo)

例如,
function
是一个特殊的操作符,可以让您看到函数名称空间中的内容。
function
在sam中有一些语法糖,即
#'
(defmacro lambda (args &body forms)
  `(function (lambda ,args ,@forms)))
(lambda (x) x)
 -> #'(lambda (x) x)