为什么 slime 的 "package" 与 inferior lisp 不同?

Why is slime's "package" different from the inferior lisp?

我想我还不清楚 slime 在 Emacs 中是如何 运行 lisp 的。

假设我有一个包含以下条目的文件:-

(defpackage "TEST"
  (:use "COMMON-LISP"))
(in-package "TEST")
*package*

现在我compile/run这三个跟其中一个说

C-c C-c
C-x C-e

我得到了输出:-

#<PACKAGE "TEST">

但是,如果我现在将缓冲区切换到劣质 lisp 缓冲区并键入

*package*

它给我的输出是

#<PACKAGE "COMMON-LISP-USER">

什么给了?使用上面的 slime 命令显然可以做一些事情,但它似乎并没有影响 inferior-lisp 的主要 REPL 循环。

文件(或实际上是缓冲区)中的当前包由编译时从编译形式向后搜索时找到的第一个顶层 in-package 形式确定,例如。 G。当使用 C-c C-c 编译顶层形式时。我希望你能想象如果不是这样的话,那迫在眉睫的混乱。

REPL 上的当前包是使用 in-package 设置的。

您可以使用 C-c C-~.

方便地将当前 REPL 包和当前目录设置为当前缓冲区的那些

全局特殊变量

由于全局变量使用动态绑定,可以重新绑定它们:

CL-USER> *package*
#<The COMMON-LISP-USER package, 117/256 internal, 0/4 external>
CL-USER> (defpackage "TEST"
           (:use "COMMON-LISP"))
#<The TEST package, 0/16 internal, 0/16 external>
CL-USER> (let ((*package* (find-package "TEST")))
           (intern "FOO"))

所以你不需要设置全局变量,你可以重新绑定它们。

所以像 SLIME 这样的东西可以重新绑定它们并在反弹变量绑定中执行评估代码:

(let ((*package* (find-package "FOO")))
  (eval (read-from-string some-string-with-code)))

线程局部全局特殊变量

也可以创建线程,这样它们就有自己的 'thread local' 全局变量:

(sb-thread:make-thread (lambda (*package*)
                                    ...)
                       :arguments (list *package*))

以上线程函数将有自己的*package*变量绑定。

IDE 和全局变量

通常人们会希望 IDE 在当前侦听器线程中使用全局变量(每个侦听器线程都应该有自己的全局变量)。

人们还希望来自编辑器的评估 Lisp 代码缓冲区使用来自该缓冲区的包(通常是顶部定义的包或代码中最近的 IN-PACKAGE 包。编辑器也可能是能够设置用于当前 Lisp 代码缓冲区的包。

然后 IDE 将在评估期间使用类似上面的内容:重新绑定 *package* 变量 and/or 使用多个线程,每个线程中都有自己的 *package* 变量绑定。

IDE 和多个劣质 Lisps

通常只有一个较差的 Lisp,但可能有多个听众。一些 IDE 可能还支持不止一种劣质 Lisp。