Common lisp 符号名称未定义变量
我有一个关于符号和全局变量之间关系的问题 符号的值属性的hyperspec状态为: 如果符号有值属性,则称其为绑定,并且该事实可由函数boundp检测。绑定符号的值单元格中包含的对象是由该符号命名的全局变量的值,可由函数symbol value访问 如果我应用以下步骤:Common lisp 符号名称未定义变量,common-lisp,Common Lisp,我有一个关于符号和全局变量之间关系的问题 符号的值属性的hyperspec状态为: 如果符号有值属性,则称其为绑定,并且该事实可由函数boundp检测。绑定符号的值单元格中包含的对象是由该符号命名的全局变量的值,可由函数symbol value访问 如果我应用以下步骤: CL-USER> (intern "*X*") *X* NIL CL-USER> (boundp '*x*) NIL CL-USER> (setf (symbol-value '*x*) 1) 1 CL-USE
CL-USER> (intern "*X*")
*X*
NIL
CL-USER> (boundp '*x*)
NIL
CL-USER> (setf (symbol-value '*x*) 1)
1
CL-USER> (boundp '*x*)
T
据我所知,上述条件均已满足。应该有一个以符号命名的全局变量,该变量的值就是符号值。但这是错误的
CL-USER> (describe '*x*)
COMMON-LISP-USER::*X*
[symbol]
*X* names an undefined variable:
Value: 1
; No value
CL-USER>
必须宣布它是特别的
CL-USER> (proclaim '(special *x*))
; No value
CL-USER> (describe '*x*)
COMMON-LISP-USER::*X*
[symbol]
*X* names a special variable:
Value: 1
; No value
CL-USER>
你能解释一下这种行为吗。什么是“未定义变量”,我在hyperspec中没有找到这个术语
(我使用SBCL 1.3.15。)
谢谢你的回答
编辑:
(由于此注释适用于下面的两个答案(用户Svante和coredump),因此我将其作为编辑而不是两个答案的注释)
我同意答案,*x*是一个全局变量
全局变量的hyperspec状态为:
“全局变量n.动态变量或常量变量。”
因此,我现在认为,SBCL说它“未定义”的原因不是它是否特殊,而是它是一个动态(特殊)变量还是一个常量变量(hyperspec:“常量变量n.一个变量,其值永远不会改变”)
下面答案中提到的第三个定义(可能我理解的答案是错误的),即根据hyperspec,它是一个不特殊(不是常数)的全局变量
你能同意吗
编辑2:
好的,总之,我想,因为hyperspec没有定义未定义的全局变量,所以它们不存在
但正确的答案是,它们确实存在并且没有定义,这意味着它取决于如何处理它们
谢谢您的回答,我接受所有三个,但我只能标记一个。有一个全局变量,它的名称是符号值。这就是输出告诉您的。未定义的是变量的状态:它是否特殊。我同意输出的措辞有点特殊
如果设置变量的值而不首先创建它(裸setq
也会这样做),那么无论它是否变得特殊,它都是未定义的
按照惯例,不使用非特殊的全局变量。这就是为什么您应该使用
defvar
,defparameter
等。正如在另一个答案中所说,*X*
不是声明特殊的(动态的)。SBCL还向您提供了一个警告,如果您在词汇上绑定了符号:
FUN> (let ((*X* 30)) (list *X* (symbol-value '*X*)))
; in: LET ((*X* 30))
; (LET ((FUN::*X* 30))
; (LIST FUN::*X* (SYMBOL-VALUE 'FUN::*X*)))
;
; caught STYLE-WARNING:
; using the lexical binding of the symbol (FUN::*X*), not the
; dynamic binding, even though the name follows
; the usual naming convention (names like *FOO*) for special variables
;
; compilation unit finished
; caught 1 STYLE-WARNING condition
(30 10)
还请注意,如果本地将*X*
声明为特殊,会发生什么情况:
FUN> (let ((*X* 30)) (declare (special *X*)) (list *X* (symbol-value '*X*)))
(30 30)
符号值
访问器从动态环境中检索绑定
根据hyperspec,不存在非特殊(非常量)的全局变量
标准中未定义实际行为,但在实现中可能会以某种方式起作用
LispWorks中的此示例:
CL-USER 46 > (boundp 'foo)
NIL
所以FOO
是未绑定的
CL-USER 47 > (defun baz (bar) (* foo bar))
BAZ
上面在LispWorks解释器中定义了一个函数baz
——它不是编译的。没有任何警告
现在我们设置这个符号foo
:
CL-USER 48 > (setq foo 20)
20
CL-USER 49 > (baz 22)
440
我们已经成功地调用了它,尽管FOO
没有声明为全局函数
让我们检查一下,如果它被宣布为特殊:
CL-USER 50 > (SYSTEM:DECLARED-SPECIAL-P 'foo)
NIL
现在我们从上面编译函数:
CL-USER 51 > (compile 'baz)
;;;*** Warning in BAZ: FOO assumed special
BAZ
编译器说它不知道FOO
,并假设它是特殊的
此行为未定义,且实现不同:
- 解释器可能只使用全局符号值,而根本不抱怨——参见上面的LispWorks示例。这在实现中比较常见
- 编译器可能会假定未定义的变量是一个特殊变量,并发出警告。这在实现中也比较常见
- 编译器可能会假定未定义的变量是一个特殊变量,并且将该变量声明为特殊变量。这并不常见——默认情况下,CMUCL做到了(做了吗?)。这种行为并不常见,也不受欢迎,因为没有标准的方法撤销声明