常见的lisp:保存图像后,SBCL得到不同的结果

时间:2014-12-02 07:56:55

标签: common-lisp packages

(这是我第一次在这里发帖提问,我搜索过但没有找到任何有用的信息......)

我发现了一个有趣的(这让我感到很困惑,因为早上一整天都是这样)。

我正在使用在Gentoo / Linux上运行的SBCL 1.1.18。这是我的问题:

假设有一个名为eql-test的软件包,它有一个asd文件,一个package.lisp和一个main.lisp(非常常见的配置)。在main.lisp中,只有一个功能:

    (defun main ()
      (format t "~a~%" (eql 'hello (read-from-string "hello"))))

现在,如果我们运行:

    sbcl --eval "(progn (load \"main.lisp\") \
      (sb-ext:save-lisp-and-die \"eql-test\" :toplevel #'main \
      :executable t))"

然后运行" eql-test"二元,我们会得到一个美丽的T。

但是,如果我们使用另一个名为" make.lisp"的文件其中包含:

    (asdf:load-system 'eql-test)
    (sb-ext:save-lisp-and-die "eql-test2"
          :toplevel #'eql-test:main
          :executable t)

然后运行:

    sbcl --load "make.lisp"

然后运行二进制文件" eql-test2",它将给出一个NIL。

我不明白为什么相同的代码给出不同的结果(肯定第二个不正确)。因为它是ASDF的隐含错误?或者我的代码有什么问题吗?

感谢您的帮助! :)

2 个答案:

答案 0 :(得分:5)

基本规则:如果有疑问,请始终控制源代码中使用的包,IO操作中,创建新符号时,搜索符号时......

如果从字符串中读取,则应确保创建的任何符号都在正确的包中。您可以绑定*package*

CL-USER 1 > *package*
#<The COMMON-LISP-USER package, 155/256 internal, 0/4 external>

CL-USER 2 > (read-from-string "FOO")
FOO
3

上方:FOO位于CL-USER包中。

让我们创建一个新包:

CL-USER 3 > (defpackage "BAR" (:use "CL"))
#<The BAR package, 0/16 internal, 0/16 external>

全局*package*未发生变化:

CL-USER 4 > *package*
#<The COMMON-LISP-USER package, 155/256 internal, 0/4 external>

绑定变量:

CL-USER 5 > (let ((*package* (find-package "BAR")))
              (read-from-string "FOO"))
BAR::FOO
3

上方:FOO位于包BAR

还要确保所有源代码都是已定义的包...确保通过加载代码的不同方式更改包...

答案 1 :(得分:0)

最后,我得到了答案似乎是正确的....在这里发布,以便可能有所帮助。

假设您希望(eq 'foo (read-from-string "foo"))返回T,其中&f; foo位于MY-PACKAGE

首先,最重要的是,如果我们执行(read-from-string "foo")(intern "foo")(find-symbol "foo")或其他任何内容,读者读取的真实符号为|foo|,这意味着&# 34; FOO&#34;小写作为符号名称,但不是我们想要的FOO。因为这些函数将完全读取您给出的符号作为字符串。因此,(read-from-string "FOO")将返回符号FOO。 - 这正是我们想要的。

第二,同样重要的是,当我们在SBCL中(save-lisp-and-die ...)时,(或者使用&#34; buildapp&#34;而不是),并运行生成的可执行图像文件,我们在COMMON-LISP-USER包中,但不是别的。所以,实际上LISP正在尝试eq MY-PACKAGE::FOOCOMMON-LISP::FOO,这将是NIL。

FIX:
(intern "FOO" :my-package)应该做到这一点。

注意:
"name"函数中的"intern"参数将是SAME作为符号名称,包括大小写。