我认为Rainer 的回答是正确的,但由于该问题出现在我对另一个问题的回答的评论中,我将包括(更新)我对该评论的回复。
符号是一个实际的对象。你可以检查它,你可以用make-symbol等创建它们。重要的是,符号是 Common Lisp 源代码的主要组成部分之一。根据词汇表条目,函数名称,尤其是在出现此问题的上下文中(函数特殊运算符的参数)是符号或形式的列表(setf符号) :
函数名n. 1.(在一个环境中)一个符号或一个列表(setf 符号),它是那个环境中一个函数的名称。2. 一个符号或一个列表(setf 符号)。
函数是一个特殊的运算符,它不计算它的参数,所以传递一个符号或setf列表意味着类似:
(function car)
(function (setf car))
并不是:
(function 'car)
(function '(setf car))
现在,词汇变量,例如x in (let ((x 42)) x),虽然在源代码中由符号表示,但在运行时实际上与符号没有任何联系。(let ((x 42)) x)的编译版本不需要知道符号x的任何信息。直观地说,这是有道理的,因为我们希望代码(let ((y 42)) y)编译成相同的东西。但是,当变量是特殊的时,与符号有联系。区别最明显的是:
(let ((x 42))
(symbol-value x))
;=> NIL
(let ((x 42))
(declare (special x)) ; or (defparameter x ...) or (defvar x ...) earlier
(symbol-value x))
;=> 42
我们希望词法作用域的函数也是如此,例如,以下代码会导致错误,因为在运行时符号x与本地函数之间没有连接:
(flet ((x () 42))
(symbol-function 'x)) ; ERROR, no function value for symbol x
但即便如此,我们仍然可以这样做:
(flet ((x () 42))
(function x))
这是因为函数是特殊的运算符,可以访问发生的环境。这意味着(因为它很特殊,并且实现使它工作)它可以知道x在这里被定义为函数。现在可能有趣的是,由于flet和labels被定义为采用函数 name,您可以这样做:
(flet (((setf kar) (value kons)
...))
...)