尖锐引用 lambda 时的非法函数调用
Illegal function call when sharp-quoting a lambda
如果这两个表达式等价
CL-USER> (lambda (x) (+ x 10))
#<FUNCTION (LAMBDA (X)) {530321CB}>
CL-USER> #'(lambda (x) (+ x 10))
#<FUNCTION (LAMBDA (X)) {5303226B}>
那为什么会出现非法函数调用错误
CL-USER> (#'(lambda (x) (+ x 10)) 10)
而这
CL-USER> ((lambda (x) (+ x 10)) 10)
20 (5 bits, #x14, #o24, #b10100)
效果很好吗?
PS 我正在使用 SBCL。
不同的有效 LAMBDA
(lambda (x) (+ x 10))
LAMBDA
是一个扩展为 (function (lambda ...))
.
的宏
#'(lambda (x) (+ x 10))
#'
是一个 reader 宏,它在读取时扩展为 (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 ...)) ...)
和 (#'(lambda ...) ...)
不是有效语法。
备注
以上内容有点令人困惑,但这就是它在语言标准中的定义方式。 lambda
宏是在 Common Lisp 的初始设计之后添加的。它允许我们编写类似于 Scheme 的代码:
(mapcar (lambda (x) (+ x 2)) '(1 2 3))
但仍然不是列表的第一个元素被求值的情况,就像在 Scheme 中那样。
原因只是句法规则:被解释为函数调用的形式可以是(参见Common Lisp Glossary):
a) function form,一种形式,它是一个列表,它的第一个元素是要调用的函数的名称,参数是评估的结果函数形式的后续元素。
b) lambda 形式,一种形式,它是一个列表,第一个元素是一个 lambda 表达式,表示要根据参数调用的函数,参数是结果评估 lambda 形式的后续元素。
换句话说,必须解释为函数调用的形式的列表只能将符号、函数名称或以 lambda
开头的列表作为第一个元素,即 lambda表达。不允许使用其他表达式(并且 #'x
只是 (function x)
的缩写,这不是两种情况之一)。
这是由于众所周知的事实,即 Common Lisp 遵循 Lisp-2 模型(参见 What is the difference between Lisp-1 and Lisp-2?)。
如果这两个表达式等价
CL-USER> (lambda (x) (+ x 10))
#<FUNCTION (LAMBDA (X)) {530321CB}>
CL-USER> #'(lambda (x) (+ x 10))
#<FUNCTION (LAMBDA (X)) {5303226B}>
那为什么会出现非法函数调用错误
CL-USER> (#'(lambda (x) (+ x 10)) 10)
而这
CL-USER> ((lambda (x) (+ x 10)) 10)
20 (5 bits, #x14, #o24, #b10100)
效果很好吗?
PS 我正在使用 SBCL。
不同的有效 LAMBDA
(lambda (x) (+ x 10))
LAMBDA
是一个扩展为 (function (lambda ...))
.
#'(lambda (x) (+ x 10))
#'
是一个 reader 宏,它在读取时扩展为 (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 ...)) ...)
和 (#'(lambda ...) ...)
不是有效语法。
备注
以上内容有点令人困惑,但这就是它在语言标准中的定义方式。 lambda
宏是在 Common Lisp 的初始设计之后添加的。它允许我们编写类似于 Scheme 的代码:
(mapcar (lambda (x) (+ x 2)) '(1 2 3))
但仍然不是列表的第一个元素被求值的情况,就像在 Scheme 中那样。
原因只是句法规则:被解释为函数调用的形式可以是(参见Common Lisp Glossary):
a) function form,一种形式,它是一个列表,它的第一个元素是要调用的函数的名称,参数是评估的结果函数形式的后续元素。
b) lambda 形式,一种形式,它是一个列表,第一个元素是一个 lambda 表达式,表示要根据参数调用的函数,参数是结果评估 lambda 形式的后续元素。
换句话说,必须解释为函数调用的形式的列表只能将符号、函数名称或以 lambda
开头的列表作为第一个元素,即 lambda表达。不允许使用其他表达式(并且 #'x
只是 (function x)
的缩写,这不是两种情况之一)。
这是由于众所周知的事实,即 Common Lisp 遵循 Lisp-2 模型(参见 What is the difference between Lisp-1 and Lisp-2?)。