在Debian上用Common Lisp和SLIME加载外部包

在Debian上用Common Lisp和SLIME加载外部包,debian,common-lisp,packages,slime,sbcl,Debian,Common Lisp,Packages,Slime,Sbcl,我在Debian挤压上使用SBCL 1.0.56,使用cl swank/slime 1:20120420-2(Debian版本号)。这些都是当前的趋势 版本不稳定 我在加载第三方CL包时遇到问题。这个 在Debian上使用CL的文档(实际上是更通用的CL Linux上的使用说明文件)是粗略的、矛盾的,而且 过时了,所以我会总结一下我所知道的。这就是我所处的位置 Debian在中安装二进制软件包(例如cl split sequence) /usr/share/common lisp/source。

我在Debian挤压上使用SBCL 1.0.56,使用cl swank/slime 1:20120420-2(Debian版本号)。这些都是当前的趋势 版本不稳定

我在加载第三方CL包时遇到问题。这个 在Debian上使用CL的文档(实际上是更通用的CL Linux上的使用说明文件)是粗略的、矛盾的,而且 过时了,所以我会总结一下我所知道的。这就是我所处的位置

Debian在中安装二进制软件包(例如cl split sequence)
/usr/share/common lisp/source
。在拆分序列的情况下,这是
/usr/share/common lisp/source/cl拆分序列

.asd文件(此处为
/usr/share/common lisp/source/cl split sequence/split sequence.asd
), 据我所知,它为CL的实现提供了指导 关于版本和依赖项,如下所示

;;; -*- Lisp -*- mode
(defpackage #:split-sequence-system (:use #:cl #:asdf))
(in-package :split-sequence-system)

(defsystem :split-sequence
    :version "20011114.1"
    :components ((:file "split-sequence")))
现在,在运行slime时,在REPL处输入以下两行 工作没有问题

(require :split-sequence)
(split-sequence:SPLIT-SEQUENCE  #\, "foo,bar")
(require:splitsequence)
调用(我认为)的内置副本 SBCL中的ASDF,它可能查看
分割序列.asd
。这 可能是SBCL特定的,请参阅。 值得注意的是,这一页,这是有用的和详细的 我遇到的任何事情,都经常提到CLC(通用 Lisp控制器),但Debian似乎正在远离这一点。看见 , 我不完全理解。无论如何,没有任何一项记录在案 使用CLC的命令对我有用。但是,CLC仍然可用 关于Debian。此外,用户邮件列表已失效-请参阅

第一次调用
(require:split sequence)
时,将对其进行编译, 并且(在我的系统上,可能是特定于Debian的)生成的
fasl
是 置于

~/.cache/common lisp/sbcl-1.0.56.0.debian-linux-x86/usr/share/common lisp/source/cl split sequence/split sequence.fasl

也就是说,文件被放置在镜像 原始源的位置。一个显而易见的问题是,这个问题如何解决 系统知道在哪里寻找包裹吗?这是我不喜欢的一件事 当然可以。看起来应该在中给出搜索路径
/etc/common lisp/source registry.conf.d
,它是ASDF的一部分 Debian包,但最接近的是
01 common lisp controller.conf
,它只是

(:directory  #p"/usr/share/common-lisp/systems/")
也许这是硬接线的地方,但我想知道

无论如何,一旦这个ASDF文件进入缓存,它就不会被再次编译, 但是,除非有人看到,否则REPL在黏液启动后不会看到它
再次要求

现在,如果我把线

(require :split-sequence)
(split-sequence:SPLIT-SEQUENCE  #\, "foo,bar")
在一个文件中,比如说
seq.lisp
,然后用C-C-k将它加载到REPL中,我得到 错误和回溯,从

The name "SPLIT-SEQUENCE" does not designate any package.
   [Condition of type SB-KERNEL:SIMPLE-PACKAGE-ERROR]
因此,我的结论是,包没有正确加载。我试过这样的变化

(asdf:oos 'asdf:load-op :split-sequence)

但是没有骰子。奇怪的是,假设我们只有这条线

(require :split-sequence)
在文件中-为清晰起见,请调用此
require.lisp
。然后加载
require.lisp
没有给出错误,然后键入

(split-sequence:SPLIT-SEQUENCE  #\, "foo,bar")
在REPL工厂!但是,在不加载
require.lisp
的情况下,键入 前一行在REPL处不起作用

因此,总而言之,如何才能成功地将包加载到 剧本我也会对上面提到的问题感兴趣,关于 ASDF是如何找到
/usr/share/common lisp/source/
位置的,但是
这更多的是一个枝节问题。

我看到了下面的帖子,上面有链接到

复制该文件顶部的代码是有效的。因此,在此文件上运行slime中的C-C-k将加载
split sequence
,并运行code
int(split sequence:split-sequence\35;\,“foo,bar”)

然而,我不知道这些神奇的咒语是做什么的。有没有人愿意解释一下,也许是另一个答案?我把它放在一个答案中,因为它是对这个问题的回答,但它并不完整,因为我不明白它为什么有效。我很乐意接受这个脚本的解释。

C-C-k编译源文件,然后加载编译后的文件

Lisp源文件包含定义和调用。文件编译器遍历文件并为其创建代码。但它并没有执行它

如果文件包含对
REQUIRE
的调用,则编译期间不会执行该调用。如果以后加载编译后的文件,将执行该命令。如果文件中的下一个Lisp表单使用的是调用
REQUIRE
后可用的某个包,那么它在编译过程中就不存在了,因为
REQUIRE
尚未执行,因此在编译过程中读取时会出现错误

基本上有两种解决方案:

  • 在使用所需功能编译特定文件之前,请执行所有必要的
    REQUIRE
    操作
  • 在编译期间执行
    REQUIRE
    语句。这就是
    EVAL-WHEN:COMPILE-TOPLEVEL
    告诉编译器在编译期间执行子表单的地方
#+:sbcl(foo)
表示当
:sbcl
是列表中的符号时(foo)是只读的
CL:*功能*
。它的使用使得编译器仅在使用SBCL时才能看到此代码

公共Lisp代码的编译需要更仔细地准备,因为:

  • 可以在文件编译期间执行Lisp代码,从而更改文件编译器的行为

  • 文件编译器的读者需要知道源代码中使用的包(符号的名称空间)


谢谢雷纳,这是一个非常清楚的解释。我引用的脚本中有多少是必要的?如果有什么用的话,
#+:sbcl
能做什么?回答我自己的问题-显然不多。只需
(在(:编译顶级:加载顶级:执行)时求值(要求:拆分序列))(打印(拆分)
(split-sequence:SPLIT-SEQUENCE  #\, "foo,bar")
#+:sbcl
(eval-when (:compile-toplevel :load-toplevel :execute)
  (require :asdf))

(eval-when (:compile-toplevel :load-toplevel :execute)
  (asdf:oos 'asdf:load-op :split-sequence))

(defpackage #:seq
  (:use #:cl #:split-sequence))
(in-package #:seq)

(print (split-sequence:SPLIT-SEQUENCE  #\, "foo,bar"))