尖锐引用 lambda 时的非法函数调用

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。

Rai*_*wig 8

不同的有效 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 中那样评估列表的第一个元素的情况。


Ren*_*nzo 7

原因只是一个语法规则:被解释为函数调用的形式可以是(参见 Common Lisp词汇表):

a)函数形式,一种形式,它是一个列表,并且具有第一个元素,该元素是要在参数上调用的函数的名称,参数是评估函数形式的后续元素的结果。

b)一个 lambda 形式,该形式是一个列表并且具有第一个元素,该元素是一个 lambda 表达式,表示要在参数上调用的函数,参数是评估 lambda 形式的后续元素的结果。

换句话说,必须被解释为函数调用的形式的列表的第一个元素只能是符号、函数名称或以 开头的列表lambda,即 lambda 表达式。不允许使用其他表达式(并且#'x只是 的缩写(function x),这不是两种情况之一)。

这是由于众所周知的事实,Common Lisp 遵循 Lisp-2 模型(请参阅Lisp-1 和 Lisp-2 之间的区别是什么?)。