为什么你的例子失败了
在 shell 中运行 sbcl --load t.cl --eval '(quit)' 时,它的作用是在进程中启动 SBCL Lisp 映像,编译文件并运行它。然后修改文件并将其保存到磁盘。最后一个动作与已经运行的 SBCL 进程无关,它已经编译了前一个文件。 SBCL 在您要求时读取文件一次,一旦它运行已编译的指令,除非您明确要求,否则没有理由再次查看文件。
使用 Emacs+SLIME 的“实时”示例
为了对正在运行的程序执行“实时”更改,您必须与已经运行的 Lisp 映像进行交互。使用 Emacs+Slime 很容易做到这一点。例如,你可以有一个这样的循环:
(defun foo (x) (+ x 3))
(dotimes (it 20)
(format t "~A~%" (foo it))
(sleep 1))
然后在 REPL 中执行期间使用新定义重新编译 foo:
(defun foo (x) (+ x 100))
另一个线程将用于重新编译函数。编译完成后,新函数将用于以后的调用。
REPL 中的输出如下所示:
3
4
5
CL-USER> (defun foo (x) (+ x 100))
WARNING: redefining COMMON-LISP-USER::FOO in DEFUN
FOO
103
104
105
...
这也适用于从另一个文件编译的 foo 的新定义,而不是直接在 REPL 中输入。
从系统外壳工作
虽然您已经可以将上面的示例用于开发目的,但您可能希望与 shell 中正在运行的 SBCL Lisp 映像进行交互。我不知道该怎么做。对于您的确切示例,您希望 SBCL 重新加载您已修改的最终文件。简单看一下SBCL manual 似乎并没有提供将 lisp 代码通过管道传输到已经运行的 SBCL 进程的方法。