Common Lisp - "constant is being redefined" with defconstant?



我正在阅读《PAIP》第5.2章。当我尝试用下面的形式定义一个常数时,完全从书上抄来的,我得到了如下所示的错误。我使用SBCL 1.1.14.debian作为解释器。我做错了什么?

(defconstant no-bindings '((t . t))
  "Indicates pat-match success, with no variables.")

常量NO-BINDINGS正在被重新定义(从(T T)到(T)。T)))

此错误表示您已经使用值'(T T)对相同名称no-bindings进行了先前的定义。

例如,在REPL中你做了一个定义:

(defconstant no-bindings '(t  t)
  "Indicates pat-match success, with no variables.")

,然后用

重新定义no-bindings
(defconstant no-bindings '((t . t))
  "Indicates pat-match success, with no variables.")

手册规定:

defconstant定义的常数可以用defconstant重新定义。但是,如果尝试使用其他操作符为符号赋值,或者使用后续的defconstant将其赋值给不同的值,则结果是未定义的。

请注意,在SBCL中,即使是相同值的双重定义,例如,在REPL中写入两次:

(defconstant no-bindings '((t . t))
  "Indicates pat-match success, with no variables.")

导致一个恒定的重定义错误,而在其他系统中(我尝试过CCL),这种情况不会发生。实际上,这是由于上述定义中对"不同价值"的解释。词汇表上说不同的不是相同的,相同的不是相等的,

 (eql '((t . t)) '((t . t)))

给出NIL,而其他相等运算符,如:

 (equal '((t . t)) '((t . t)))

返回T

因此,SBCL似乎正确地遵循了形式规范,与其他系统不同。

一个常量是一个不能被改变的值。因此,您应该使用它的绝对确定性,如(defconstant +pi+ 3.1415927)

在实践中,

是可变的,但是使用它的每个函数或宏可能都利用了它作为常量的优势,并在实际值中编译,因此更改它不会受到这些影响。因此,更改常量应该通过重新编译/重新加载所有内容来完成,以确保它已更新。

对于被认为是常量但可能会更改的值,使用defparameter。如。(defparameter *no-bindings* '((t . t)) "Indicates pat-match success, with no variables.")

最新更新