lambda表达式宏或标记是否在公共Lisp中?
我试图通过《CommonLisp:符号计算的温和介绍》一书来学习CommonLisp。此外,我正在使用SBCL、Emacs和Slime 在第7章中,作者就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
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)