0

我下载了一个大型软件项目FriCAS,我从源代码编译并使用 SBCL。这只是使用 GNU .configure 的问题——我是一个完整的 Lisp 新手。

但是,为了添加一些进一步的功能,我已经非常仔细地按照说明安装了 quicklisp 和一些额外的包。到目前为止,一切都很好。

这是我的问题:我正在尝试编译一个外部 lisp 文件以在系统中使用。我需要让 quicklisp 及其包对编译器可见。因此,我将 .sbclrc 文件复制到了 lisp 文件的顶部:

#-quicklisp
(let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp"
                                       (user-homedir-pathname))))
  (when (probe-file quicklisp-init)
    (load quicklisp-init)))

我跟着这个

(eval-when (:compile-toplevel)
  (ql:quickload "f2cl-lib"))

我已经安装f2cl-lib了 quicklisp。但是,我的编译器(在 FriCAS 内)立即中止

; caught ERROR:
;   READ error during COMPILE-FILE:
;   
;     Package QL does not exist.

我在这里有点难过 - 可能缺少一些微不足道和明显的东西,但正如我从新手的角度说的那样,我不知道它是什么。

4

1 回答 1

2

看起来像一个常见问题解答。另请参阅eval-when.

文件编译器

请记住,文件编译器编译表单而不执行它们。它只是为以后执行生成代码。一般来说。不过,在 Common Lisp 中,这条规则有一些例外:例如,源代码中使用的将由文件编译器运行。但是 Common Lisp 还允许我们告诉文件编译器在编译时执行代码,这是eval-when.

你的例子简化了

如果你有一个文件:

(load "file-which-creates-package-foo")

(eval-when (:compile-toplevel)
  (foo:bar)) 

然后文件编译器会生成加载文件的代码,但不会加载文件。

接下来,文件编译器看到第二种形式,其中文件编译器被指示在编译时执行一条语句(并且仅在编译时),因此(foo:bar)将在编译时执行。但更糟糕的是:由于加载代码还没有执行,包FOO是未知的,并且在编译时(foo:bar)会读取表单,阅读器在编译时已经抱怨包不存在。FOO

EVAL-WHEN的使用

你需要做的是告诉文件编译器在编译期间实际加载它需要的东西。该文件已经包含一个eval-when表单,因此应该给您一个提示:使用eval-when. 它有三种情况

  • :compile-toplevel -> 文件编译器执行包含的表格
  • :load-toplevel -> 文件编译器生成代码,以便在加载代码时执行代码
  • :execute

确保在应该执行代码时提到了这些情况。

可能的解决方案

所以有可能的解决方案:

  • 如上,用于EVAL-WHEN能够通过文件编译器执行表单
  • 将加载代码写入单独的文件并在使用包之前编译/加载此文件。还可以将此文件添加到系统中,以便在编译使用代码之前由编译系统加载该文件。
于 2015-10-24T05:11:44.533 回答