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

4

考虑到这种情况:

(defmacro mac1 ...)

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

在实时环境中重新定义mac1不会影响func1,除非它本身被重新编译。

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

在源代码中添加类似以下内容将被接受:

(watch
  (defmacro mac1 ...))

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

这并不难实现,但我更愿意避免重复造轮子。


1
不是真正的答案,但如果你愿意进入cl包,你可以在defun的包装器中将函数源代码作为其符号名称的属性存储,并在defmacro周围有第二个包装器来查看who-macroexpands并迭代这些存储的源代码。或者当您迷失了对宏编辑可能会做什么的跟踪时,只需使用slime-compile-and-load-file - BRPocock
2个回答

5
宏不一定被编译。如果您使用SBCL(参见手册),则有一个名为sb-ext:*evaluator-mode*的变量,可以将其设置为:interpret,以便在评估期间扩展宏。其他实现可能提供类似的功能。这使您能够更改宏的定义,而无需重新编译函数调用点,就像您已经使用函数一样。
或者,slime定义了一个名为slime-who-macroexpands的函数。您需要深入了解它的工作方式,并可能在Common Lisp环境(swank)或emacs端利用它。

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保留了一个“谁调用”数据库,因此可以重新编译所有直接使用和依赖其他函数/宏的函数。
编辑器具有“编辑调用者”和“继续标签搜索”命令,以查找调用者,然后手动重新编译它们。编写一个编辑器命令以重新编译所有调用者应该很容易/可能。

最后一个例子有点误导人,重新编译已经编译过的函数对大多数实现没有影响,绝对对所有编译成本机代码的当前实现都没有影响。请在例子上方或下方添加一条备注。 - acelent
1
注意:SBCL的类似函数是sb-introspect:who-macroexpands,而Slime函数是slime-who-macroexpands。但是,sb-introspect:who-macroexpands返回一个符号和definition-source结构的关联列表,将符号传递给compile没有任何效果;你可能需要使用definition-source-pathname或其他东西来跟踪它。 - BRPocock

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接