Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Common lisp 符号名称未定义变量_Common Lisp - Fatal编程技术网

Common lisp 符号名称未定义变量

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

我有一个关于符号和全局变量之间关系的问题

符号的值属性的hyperspec状态为:

如果符号有值属性,则称其为绑定,并且该事实可由函数boundp检测。绑定符号的值单元格中包含的对象是由该符号命名的全局变量的值,可由函数symbol value访问

如果我应用以下步骤:

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做到了(做了吗?)。这种行为并不常见,也不受欢迎,因为没有标准的方法撤销声明