sds 的答案有效,除了您可能只想在执行bar
时提供建议sample
,因此您还需要建议 sample 以激活和停用bar
. 我的with-temporary-advice
宏促进了这一点:
(defmacro with-temporary-advice (function class name &rest body)
"Enable the specified advice, evaluate BODY, then disable the advice."
`(unwind-protect
(progn
(ad-enable-advice ,function ,class ,name)
(ad-activate ,function)
,@body)
(ad-disable-advice ,function ,class ,name)
(ad-activate ,function)))
(defadvice bar (around my-conditional-bar disable)
;; This advice disabled by default, and enabled dynamically.
(when condition
ad-do-it))
(defadvice sample (around my-sample-advice activate)
"Make execution of `bar' conditional when running `sample'."
(with-temporary-advice 'bar 'around 'my-conditional-bar
ad-do-it))
请注意,如果在执行bar
时也以其他方式调用sample
,建议也将适用于这些调用,因此如果有可能,您应该考虑到这一点。
或者,您可能更喜欢在需要时使用flet
来重新定义bar
。当然,这与第一个解决方案相同。
(defadvice sample (around my-sample-advice activate)
"Make execution of `bar' conditional when running `sample'."
(if condition
ad-do-it
(flet ((bar () nil))
ad-do-it)))
这更容易阅读,但由于我不明白的原因flet
,从 Emacs 24.3 开始,不再受欢迎。它的文档字符串建议cl-flet
改用,但由于cl-flet
使用词法绑定,这实际上不起作用。据我所知,这听起来flet
并没有真正消失,但目前的建议似乎是使用建议。
另请注意,如果在内部bar
,不需要的行为取决于某个变量,那么最好使用let
对该变量的绑定而不是对flet
函数的绑定。
编辑:
当然,这些方法确实让我们更难看到正在发生的事情。根据具体情况,最好简单地重新定义sample
函数以执行您想要的操作(或者my-sample
按照您的建议编写一个函数来调用它)。