Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Common lisp common lisp:保存图像后与SBCL得到不同的结果_Common Lisp_Packages - Fatal编程技术网

Common lisp common lisp:保存图像后与SBCL得到不同的结果

Common lisp common lisp:保存图像后与SBCL得到不同的结果,common-lisp,packages,Common Lisp,Packages,(这是我第一次在这里发帖,我搜索了一下,但没有找到任何有用的信息……) 我在common lisp中发现了一个有趣的东西(让我困惑了整整一个上午) 我使用的是在Gentoo/Linux上运行的SBCL 1.1.18。我的问题是: 假设有一个名为eql test的包,它有一个asd文件、一个package.lisp和一个main.lisp(非常常见的配置)。在main.lisp中,只有一个函数: (defun main () (format t "~a~%" (eql 'hel

(这是我第一次在这里发帖,我搜索了一下,但没有找到任何有用的信息……)

我在common lisp中发现了一个有趣的东西(让我困惑了整整一个上午)

我使用的是在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测试”二进制文件,我们将得到一个漂亮的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的一个隐式bug?或者我的代码有什么问题


谢谢你的帮助!:)

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

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

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

CL-USER 2 > (read-from-string "FOO")
FOO
3
全局
*包*
未更改:

CL-USER 4 > *package*
#<The COMMON-LISP-USER package, 155/256 internal, 0/4 external>
上图:
FOO
在包
栏中


还要确保任何源代码都是已定义的包。。。确保程序包没有被加载代码的不同方式更改…

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

假设您希望
(eq'foo(从字符串“foo”读取))
返回T,哪个'foo在
MY-PACKAGE

首先,也是最重要的,如果我们做
(从字符串“foo”读取)
(intern“foo”)
(查找符号“foo”)
或其他任何事情,读者读取的真正符号是
|foo |
,意思是小写的“foo”作为符号名,而不是我们想要的
foo
。因为这些函数将准确地读取您作为字符串给出的符号。因此,
(从字符串“FOO”读取)
将返回一个符号
FOO
-这正是我们想要的

其次,同样重要的是,当我们在SBCL中
(保存lisp和die…
(或者改用“buildapp”)并运行生成的可执行映像文件时,我们在
COMMON-lisp-USER
包中,而不是在其他包中。因此,实际上LISP正在尝试
eq
MY-PACKAGE::FOO
COMMON-LISP::FOO
,这将是零

修复:
(实习“FOO”:我的软件包)
应该可以

注意:

“intern”
函数中的
“name”
参数将与符号名称相同,包括大小写

是不是
eql测试中的
'hello
在某个
:eql测试
命名空间中,但是从字符串读取的
使用某个顶级命名空间限定了名称?@Cactus感谢您的评论。等等……哈哈!就这样!这正是你提到的-我把所有的东西都搬到了cl用户那里,它成功了!这应该是因为这两个符号不在同一名称空间中……但我仍然不明白为什么直接“加载”和“加载系统”的输出不同?它们应该是相同的,因为ASDF不应该影响包的名称空间……好吧,我想我知道原因……(从字符串读取)将把符号插入cl用户包,而文字符号将插入代码所在的包中……是的,这大致就是我的意思。当您
(加载“main.lisp”)
时,我假设没有任何包向导发生,因此这相当于复制粘贴
main.lisp
的内容,因此最初出现了
'hello
(在
main
的定义中)被实习到
cl:user
。也许我应该把它作为一个正确的答案发布。。。但我对SBCL和ASDF的内部结构了解不够,无法确定。我口齿不清的日子已经过去了:)谢谢你的帮助。但我的观点是,如果在slime中运行该程序,(从字符串“foo”读取)将返回TEST-EQL包中的符号。但是,当您(保存lisp和die…)文件到可执行映像中并再次运行它时,(从字符串读取)符号将出现在CL-USER包中。(注意,(从字符串读取)在TEST-EQL包中。)这很奇怪:(
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