在 emacs/slime 实时环境中自动重新编译

Automating recompilation in emacs/slime live environment

鉴于这种情况:

(defmacro mac1 ...)

(defun func1 () 
  (mac1 ...))

在实时环境中重新定义 mac1 不会影响 func1,直到它自己重新编译。

有没有办法让 emacs 或 lisp 在重新编译 mac1 时自动重新编译 func1

源代码中类似这样的内容是可以接受的:

(watch
  (defmacro mac1 ...))

(on-signal (mac1)
  (defun func1 ...))

实施起来并不难,但我宁愿避免重新发明轮子。

宏不一定被编译。如果您正在使用 SBCL(请参阅 manual),则有一个名为 sb-ext:*evaluator-mode* 的变量可以设置为 :interpret,以便在计算期间扩展宏。其他实现可能会提供类似的东西。这允许您更改宏的定义,而无需像您已经对函数所做的那样重新编译调用站点。

或者,slime 定义了一个名为 slime-who-macroexpands 的函数。您必须深入了解它是如何工作的,并可能在 Common Lisp 环境 (swank) 或 emacs 端利用它。

例如,在 LispWorks 中,您可以执行以下操作。可能 SBCL 有类似的设施。

假设我们有这个:

(defmacro foo ()
  `(list 1 2 3))

(defun bar () (first (foo)))
(defun baz () (second (foo)))

现在你可以询问谁打电话给 foo:

CL-USER 11 > (who-calls 'foo)
(BAZ BAR)

这使得重新编译这两个函数变得容易:

CL-USER 12 > (mapcar 'compile (who-calls 'foo))
;;;*** Warning in BAZ: The definition of BAZ is already compiled.
;;;*** Warning in BAR: The definition of BAR is already compiled.
(BAZ BAR)

由于 LispWorks 保留了一个调用者数据库,因此可以重新编译所有直接使用和依赖于其他函数的函数 functions/macros。

编辑器有命令Edit CallersContinue Tags Search来查找调用者,然后手动重新编译它们。应该easy/possible写一个重新编译所有调用者的编辑器命令。