(这是我第一次在这里发帖提问,我搜索过但没有找到任何有用的信息......)
我发现了一个有趣的(这让我感到很困惑,因为早上一整天都是这样)。
我正在使用在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的隐含错误?或者我的代码有什么问题吗?
感谢您的帮助! :)
答案 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::FOO
和COMMON-LISP::FOO
,这将是NIL。
FIX:
(intern "FOO" :my-package)
应该做到这一点。
注意:
"name"
函数中的"intern"
参数将是SAME作为符号名称,包括大小写。