“常数被重新定义”与defconstant?

时间:2015-07-08 04:21:44

标签: common-lisp

我正在阅读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)))

2 个答案:

答案 0 :(得分:1)

常量是每个规格的一个值,不应该被改变。因此你应该将它用于绝对的确定性,如(defconstant +pi+ 3.1415927)

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

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

答案 1 :(得分:0)

错误表示您已使用值no-bindings完成了同名'(T T)的先前定义。

例如在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.")

manual指定:

  

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

<强>更新

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

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

导致不断重新定义错误,而在其他系统中(我尝试过CCL),这不会发生。实际上这是由于上述定义中对“不同价值”的解释。词汇表说不同的是不一样的,同样不是eql和

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

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

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

返回T

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