common-lisp - SBCL: asdf:load-system 在定义字符串常量时失败

标签 common-lisp sbcl

使用 SBCL,当 lisp 代码定义字符串常量时,我​​的系统无法加载通过 ASDF 定义的问题。
这是代码:

常量.lisp

(defconstant A 1.0)
(defconstant B "B")

简单的.asd
(defsystem :simple
:components ((:file "constants")))

通过加载
(asdf:load-system "simple")

我收到以下错误(输出已缩短了一点):
* (asdf:load-system "simple")  
; compiling file "/Users/.../constants.lisp"
; compiling (DEFCONSTANT A ...)
; compiling (DEFCONSTANT B ...)
; /Users/.../constants-TMP.fasl written
; compilation finished in 0:00:00.003

debugger invoked on a DEFCONSTANT-UNEQL in thread
#<THREAD "main thread" RUNNING {1002BFEA93}>:
   The constant B is being redefined (from "B" to "B")

clisp、ccl 和 abcl 没有出现错误。
此外,通过加载文件
(load "constants.lisp")

工作正常。

我正在使用

SBCL 1.2.14、ASDF 3.1.3、MacOS

感谢您的任何提示,

奥利弗

最佳答案

为什么字符串常量失败?

defconstant 的规范告诉我们:

However, the consequences are undefined if an attempt is made to assign a value to the symbol using another operator, or to assign it to a different value using a subsequent defconstant.



这里的重要词是不同的:根据哪个比较?

The consequences are undefined if there are any bindings of the variable named by name at the time defconstant is executed or if the value is not eql to the value of initial-value.



比较由 完成eql .

SBCL 编译您的文件,然后加载结果(xxx-TMP.fasl 文件),对于该特定实现,defconstant form 因此在同一环境中被评估两次。编译器不需要在编译期间实际评估表单(它可以以某种方式在内部声明它,以便可以内联常量的进一步使用),但这是一个有效的编译策略。

这里,由于编译环境和加载环境是一样的,而且因为两次出现的字符串不完全相同(不是eq),所以提示了一个错误。如果你碰巧用另一个相同版本的 SBCL 解释器实例加载 FASL 文件,它不会给你这个错误。

你能做什么?
  • 不要重新发明轮子,使用 alexandria:define-constant ,它允许指定在哪个测试函数下该值是常量:
    (alexandria:define-constant b "B" :test #'string=)
    

    因此,当它被多次评估时,新的 "B"使用 string= 将值与现有值进行比较,并且由于它们相等,因此不会执行其他操作。
  • 使用 defvar并且在部署代码之前不要再担心它(通常在开发过程中需要更改常量)。
  • 关于common-lisp - SBCL: asdf:load-system 在定义字符串常量时失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34800988/

    相关文章:

    lisp - 如何在 Common Lisp 中将元素从一个列表移动到另一个列表 - CLisp

    rest - Common Lisp 中的具象状态转移 (REST)

    if-statement - `if` 的替代实现 - 难以理解的行为

    performance - 如何提高Common Lisp中逐行读取大文件的速度

    c - C 函数 fread 在 Common Lisp 中的等价物是什么?

    python - SBCL 程序 I/O 互操作性

    lisp - 嵌套 alist 到 plist 与 alexandria

    common-lisp - 我需要一个多合一的 lisp 引用

    vector - 为什么这个 lisp 向量没有扩展?

    lisp - CentOS 7 上的 Common Lisp