advice-add 参数问题

ScratchBuffer里面


(defun my-function (arg)
  "test my-function"
  (interactive "stest:")
  (message arg))
(advice-add 'my-function
            :before
            (lambda () (message "Before calling my-function")))

(advice-add 'my-function
            :after
            (lambda (&rest _) (message "After calling my-function")))


不懂就问,上面执行M-x my-function 然后随便输入点什么,执行的时候报错 apply: Wrong number of arguments: (lambda nil (message “Before calling my-function”)), 1 是为什么?

在看了 关于 advice 的参数数目 - #14,来自 et2010 后,

(advice-add 'my-function
            :before
            (lambda (&rest _) (message "Before calling my-function")))


(advice-add 'my-function
            :after
            (lambda (&rest _) (message "After calling my-function")))

给加了参数,但是好像还是没能解决问题,还是报错

然后我猜想是不是 我再去 在Scratch 中 C-j,它就又加了一个 advice。那相当于我有好几个before了(执行了好几次)。那么这种情况下,想问

  1. 怎么清除所有的advice,(advice-mapc #'advice-remove 'my-function) chatgpt给了一个这个,但是好像不行
  2. 我在Scratch中 C-j 运行生效的函数,怎么让他失效,不能重启吧。。。

advice-add 最好不要用lambda. 用defun 这样不会重复 add,而且也方便remove.

那现在有办法清除所有的advice吗

我不太想解釋怎么做的,看 nadvice.el 代码得出的

(remove-function
 (symbol-function 'my-function)
 (lambda () (message "Before calling my-function")))
(remove-function
 (symbol-function 'my-function)
 (lambda (&rest _) (message "After calling my-function")))


新版的 advice 是用重新抽象出来的 oclosure 实现的,旧版也有同样界面的 API 不过是通过注入 byte-code 实现的

(oclosure-define (advice
                  (:predicate advice--p)
                  (:copier advice--cons (cdr))
                  (:copier advice--copy (car cdr how props)))
  car cdr how props)

如果是两个 advice 都在的情況

(advice--car (symbol-function 'my-function))
;; (lambda (&rest _) (message "After calling my-function"))

(advice--car (advice--cdr (symbol-function 'my-function)))
;; (lambda nil (message "Before calling my-function"))

(advice--cdr (advice--cdr (symbol-function 'my-function)))
;; (lambda (arg) "test my-function" (interactive "stest:") (message arg))

如果没法通过 equal 比较删除,手动 fset 回去也不是不行。

或者写个函数

(defun advice-last (f)
  (if (advice--p f)
      (advice-last (advice--cdr f))
    f))
(fset 'my-function (advice-last (symbol-function 'my-function)))

这种自己写了个函数的情况,估计还是 fmakunbound 再 eval 定义会快些

可以参考这个帖子