use*_*846 1 lisp lambda common-lisp
如果这两个表达式等价
CL-USER> (lambda (x) (+ x 10))
#<FUNCTION (LAMBDA (X)) {530321CB}>
CL-USER> #'(lambda (x) (+ x 10))
#<FUNCTION (LAMBDA (X)) {5303226B}>
Run Code Online (Sandbox Code Playgroud)
那为什么我会在这里收到非法函数调用错误
CL-USER> (#'(lambda (x) (+ x 10)) 10)
Run Code Online (Sandbox Code Playgroud)
而这
CL-USER> ((lambda (x) (+ x 10)) 10)
20 (5 bits, #x14, #o24, #b10100)
Run Code Online (Sandbox Code Playgroud)
效果很好吗?
PS我正在使用SBCL。
不同的有效 LAMBDA
(lambda (x) (+ x 10))
Run Code Online (Sandbox Code Playgroud)
LAMBDA是一个扩展为(function (lambda ...)).
#'(lambda (x) (+ x 10))
Run Code Online (Sandbox Code Playgroud)
#'是一个读取器宏,在读取时扩展为(function ...).
((lambda ...) ...)是 Common Lisp 中的内置语法。它被定义为一个有效的形式,一个有效的 Lisp 表达式。
使用 LAMBDA 的 Lisp 表单语法无效
((function (lambda ...)) ...) 在 Lisp 中不是有效的语法。
复合 Lisp 形式的有效语法
Common Lisp 中只有以下复合形式有效:
(<special-operator> ...) 对于内置的特殊运算符之一(<macro-operator> ...)(<function-operator> ...)(<lambda-expression> ...)运算符是符号。后者然后有一个 lambda 表达式作为它的第一个元素。例子:
((lambda (x) (1+ x)) 41)
其他句法变体在 Common Lisp 中无效。因此((function (lambda ...)) ...)and 也不(#'(lambda ...) ...)是有效的语法。
笔记
上面有点令人困惑,但这就是它在语言标准中的定义。这个lambda宏是在 Common Lisp 的初始设计之后添加的。它允许我们写类似于 Scheme:
(mapcar (lambda (x) (+ x 2)) '(1 2 3))
Run Code Online (Sandbox Code Playgroud)
但是仍然不是像在 Scheme 中那样评估列表的第一个元素的情况。
原因只是一个语法规则:被解释为函数调用的形式可以是(参见 Common Lisp词汇表):
a)函数形式,一种形式,它是一个列表,并且具有第一个元素,该元素是要在参数上调用的函数的名称,参数是评估函数形式的后续元素的结果。
b)一个 lambda 形式,该形式是一个列表并且具有第一个元素,该元素是一个 lambda 表达式,表示要在参数上调用的函数,参数是评估 lambda 形式的后续元素的结果。
换句话说,必须被解释为函数调用的形式的列表的第一个元素只能是符号、函数名称或以 开头的列表lambda,即 lambda 表达式。不允许使用其他表达式(并且#'x只是 的缩写(function x),这不是两种情况之一)。
这是由于众所周知的事实,Common Lisp 遵循 Lisp-2 模型(请参阅Lisp-1 和 Lisp-2 之间的区别是什么?)。