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

时间:2016-06-18 13:44:17

标签: emacs macros common-lisp slime

鉴于这种情况:

(defmacro mac1 ...)

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

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

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

源中的这样的东西是可以接受的:

(watch
  (defmacro mac1 ...))

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

并不难实现,但我宁愿避免重新发明。

2 个答案:

答案 0 :(得分:5)

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

或者,slime定义了一个名为slime-who-macroexpands的函数。在Common Lisp环境(swank)或emacs方面,你需要挖掘一下它是如何工作的,也许可以利用它。

答案 1 :(得分:1)

例如,在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保留了一个who-calls数据库,因此可以重新编译所有直接使用并依赖于其他函数/宏的函数。

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