鉴于这种情况:
(defmacro mac1 ...)
(defun func1 ()
(mac1 ...))
在实时环境中重新定义mac1
不会影响func1
,直到它自身重新编译。
有没有办法让emacs或lisp在重新编译func1
时自动重新编译mac1
?
源中的这样的东西是可以接受的:
(watch
(defmacro mac1 ...))
(on-signal (mac1)
(defun func1 ...))
并不难实现,但我宁愿避免重新发明。
答案 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 Callers
和Continue Tags Search
来查找调用者,然后手动重新编译它们。编写一个重新编译所有调用者的编辑器命令应该很容易/可能。