为什么 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。
我想我还不清楚 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-~
.
全局特殊变量
由于全局变量使用动态绑定,可以重新绑定它们:
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。