首页
归档
友情链接
关于
Search
1
在wsl2中安装archlinux
295 阅读
2
从零开始配置 vim(15)——状态栏配置
174 阅读
3
nvim番外之将配置的插件管理器更新为lazy
162 阅读
4
2018总结与2019规划
150 阅读
5
PDF标准详解(五)——图形状态
127 阅读
软件与环境配置
读书笔记
编程
Thinking
FIRE
菜谱
翻译
登录
Search
标签搜索
c++
c
emacs
学习笔记
elisp
windows
文本操作术
编辑器
NeoVim
Vim
win32
读书笔记
VimScript
linux
文本编辑器
投资理财
Java
反汇编
OLEDB
数据库编程
Masimaro
累计撰写
457
篇文章
累计收到
33
条评论
首页
栏目
软件与环境配置
读书笔记
编程
Thinking
FIRE
菜谱
翻译
页面
归档
友情链接
关于
搜索到
1
篇与
的结果
2026-10-19
《elisp 每日一练》——Advice 函数修饰机制入门
在前面我们了解了hook机制以及如何定义和执行hook。利用hook可以很方便的对一些事件进行处理。但是它最大的问题在于,需要程序的设计者预先留下可供hook的槽点。有时候设计者没有预留对应的hook,但是我们又需要在它执行的前后做文章、或者修改它的行为。这个时候我们可以使用Advice机制背景知识它可以在不修改原函数的情况下,为其附加额外行为。你可以把它理解为对函数进行“建议”或“增强”。它是一种可以不需要预先埋设hook点位的hook。现代Emacs更推荐使用 advice-add 和 advice-remove 进行添加和删除函数的advice。函数的签名如下:(advice-add SYMBOL HOW FUNCTION &optional PROPS)第一个参数 SYMBOL 是函数的符号。而HOW 则是advice接管函数的方式,它有以下几种形式:around, 这是最强大、最灵活的类型。我们传入的 FUNCTION 函数会完全接管原始函数,但原始函数会作为一个额外的参数 (orig-fun) 传递给你。此时在函数内部你可以自由的调整调用原函数的时机、参数等:before, 在原始函数之前执行 advice 函数, 两者接收相同参数,但返回值始终是原始函数的返回值。这类似于在函数入口处执行一个“前置动作”。:after, 在原始函数之后执行 advice 函数。两者接收相同参数,返回值仍是原始函数的返回值。这类似于在函数调用完成之后执行一个“清理动作”。:override, 完全替换原始函数, 它类似于使用 fset 替换函数符号绑定的函数,对于一些重要功能的函数,替换之后会出现大面积的问题,所以应该谨慎使用除了这四个基本的以外,还提供了 :after-until、after-while 这种根据原函数返回值决定是否调用advice函数和 :before-until、:before-while 这类根据advice 函数返回值来决定是否执行原函数的控制方式。advice 机制还能处理原函数的返回值和接收参数,可以通过 :filter-args 和 :filter-args。例如下面是一个控制原函数返回值的示例:(defun my-double (x) (* x 2)) (defun my-increase(x) (1+ x)) (advice-add 'my-double :filter-return 'my-increase) (my-double 3) ;; ==> 这里返回的值不再是6,而是7从这里,相比读者已经看出来它的弊端了。某些时候它会破坏原函数的行为,就像这个例子,如果函数的调用者不知道某个插件或者配置导致增加了函数的advice,他可能无论如何也无法理解为什么这里返回值跟预想中不一致。而且有时候advice使用不当会导致无限递归,或者其他致命的错误。所以在存在hook的情况下,优先选择使用hook,应该将 advie 作为没办法的办法。作为最后的手段。对于一些特别重要的函数,你不确定它是否存在 advice、可以使用 advice-member-p 进行判断。然后利用 addvice-remove 进行清理。练习本节我们来对某些重要的函数实现一个统计耗时的功能。例如我们以find-file-noselect 为例(defun my-timed-find-file-noselect (origin-fun &rest args) (let ((start (float-time)) (file (car args))) (unwind-protect (apply origin-fun args) (message "find-file-noselect %S: %.3fs" file (- (float-time) start))))) (advice-add 'find-file-noselect :around 'my-timed-find-file-noselect)这段代码不难理解,我们通过 :around 包裹,在函数调用之前记录一次时间,然后调用函数,在函数结束之后再调用一次。最终返回时间。上面代码调用原始函数的部分使用 unwind-protect,该函数是一种异常处理机制,你可以理解为一般编程语言中异常处理中的final。它保证BODY中的代码不论以何种形式退出,都会执行 CLEANUP 里面的代码总结我们今天了解了 addvice 机制。今天介绍的函数如下:advice-addadvice-removeadvice-member-p
2026年10月19日
1 阅读
0 评论
0 点赞