当我运行 find-data-from-command 函数时没有首先执行包的“快速加载”,它工作正常。如果我加载包,它会给出拆分序列未定义的错误。
我试图在加载自定义包后重新加载拆分序列。没用
(ql:quickload :<a-custom-package>)
(defun find-data-from-command (x desired-command)
(setq desired-data ())
(loop for line = (read-line x nil)
while (and line (not desired-data)) do
(progn
(setq commands (first (split-sequence ":" line)))
(setq data (split-sequence "," (first (rest (split-sequence ":" line)))))
(print (cons "command:" commands))
(cond
((equal commands desired-command) (return-from find-data-from-command data))))))
FIND-DATA-FROM-COMMAND
SIGMA 24 >
(setq obj-type (find-data-from-command (open "log.txt") "types"))
Error: Undefined operator SPLIT-SEQUENCE in form (SPLIT-SEQUENCE ":" LINE).
最佳答案
问题与 Quicklisp 无关,它与您在某处定义的名为 SIGMA
的包有关。特别是在您的代码中的某处是一个看起来像这样的表单:
(defpackage "SIGMA" ;or :sigma or :SIGMA or #:sigma or ...
...
(:use ...)
...)
后来
(in-package "SIGMA")
问题是你的包定义有一个显式的 (:use ...)
子句。
defpackage
,以及底层函数 make-package
:use
子句(或 make-package
中的关键字参数)有一些有趣的行为:
- 如果没有给出,则有一个实现定义的默认值;
- 如果给出了一个,那么它将覆盖默认值。
我认为,这个想法是实现可能想要提供一堆默认情况下可用的附加功能,并且这些功能不能在 CL
包中,因为它的内容包在标准中定义。所以如果你只是说
(defpackage "FOO")
然后允许(也许鼓励)实现,使 FOO
的使用列表中包含一些有用的包。这些包可能与 CL-USER
的默认使用列表中的包相同,但我不确定这是必需的:整个事情有点不明确。
这样做的最终结果是,如果您想要定义既使用实现定义的功能又并且具有显式使用列表的包,您必须诉诸一些小技巧。你如何做到这一点完全取决于你,但由于你是在定义这样的包的地方编写依赖于实现的代码,你可能想通过某种形式明确表示你正在做的是依赖于实现的,比如
(defpackage :foo
(:use ...)
#+LispWorks
(:use :lispworks :harlequin-common-lisp :cl)
...)
或者,如果您只想要一些特定的符号集
(defpackage :foo
(:use ...)
#+LispWorks
(:import-from :lispworks #:split-sequence))
请注意,这与使用包含符号的包并不完全相同。
在所有这些情况下,如果您的代码自称是可移植的,那么应该有适用于其他实现的适当子句,以及一种了解您何时尝试在您尚未见过的实现上运行的方法:如何做到这一点我认为超出了这个答案的范围。
关于lisp - 快速加载 lisp 后未定义的运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58107583/