Common lisp——为啥这个符号不是外部的?
Posted
技术标签:
【中文标题】Common lisp——为啥这个符号不是外部的?【英文标题】:Common lisp — why isn't this symbol external?Common lisp——为什么这个符号不是外部的? 【发布时间】:2020-05-15 14:23:15 【问题描述】:我正在尝试在 ASDF 中运行测试,如下所示:
;;;; foo.asd
(defsystem "foo/tests"
:depends-on ("foo"
"fiveam")
:components ((:module "tests"
:components
((:file "main"))))
:perform (test-op (op c) (symbol-call :fiveam '#:run! 'foo/tests:all-tests))
我的tests/main.lisp
文件是这样开始的:
;;;; tests/main.lisp
(defpackage foo/tests
(:use :cl
:foo
:fiveam)
(:export :#run! :#all-tests))
(in-package :foo/tests)
当我在 REPL 中运行 (asdf:test-system 'foo)
时,我会使用 LOAD-SYSTEM-DEFINITION-ERROR
进入调试器。调试器抱怨The symbol "ALL-TESTS" is not external in the FOO/TESTS package.
但是,我显然是在 foo/tests
包中导出符号。有人可以告诉我我在这里缺少什么以及为什么 Lisp 编译器没有看到外部符号吗?非常感谢。
【问题讨论】:
foo.asd
在main.lisp
加载之前被读取,所以defpackage
还没有被执行。
@Barmar:这就是symbol-call
表单解决的问题。
@svante: foo/tests:all-tests
是尚未定义 (?) 包中的外部符号。 symbol-call
如何解决这个问题,它不是在读取时执行的?在读取 DEFSYSTEM 表单之前,他需要以某种方式获得该软件包?
@RainerJoswig:对不起,你们都说得对,我只是看了一眼表格。正如所写,它只解决了fiveam:run!
的问题,而不是论点。
早就有人说,选择在 CLTL 的第 11 章中描述包是经过深思熟虑的。
【参考方案1】:
uninterned 符号的语法是#:foo
,而不是:#foo
。
您还需要在运行时解析:perform
表单中的符号,例如。 G。通过uiop:find-symbol*
,就像你在那里使用uiop:symbol-call
一样。
:perform (test-op (op c)
(symbol-call :fiveam '#:run!
(find-symbol* '#:all-tests '#:foo/tests)))
或者,由于您似乎从测试包中导出了 run!
函数,您可能想要调用它而不是 fiveam:run!
:
:perform (test-op (op c)
(symbol-call '#:foo/tests '#:run!))
【讨论】:
以上是关于Common lisp——为啥这个符号不是外部的?的主要内容,如果未能解决你的问题,请参考以下文章
为啥这个 Common Lisp 宏不起作用?书上的答题卡错了吗?
为啥这个在 Common Lisp 中漂亮地打印宏扩展的宏不起作用?都有哪些替代工具?
在 Common Lisp 中,符号名称是不是有定义的最大长度?