Emacs 27.1回调报(void-variable buffer)错误,Elisp不支持闭包吗?
问题解答
Emacs Lisp 完全支持闭包特性,你遇到的(void-variable buffer)错误和闭包本身无关,核心原因是没有启用词法绑定(lexical binding)——Elisp默认使用动态绑定,只有开启词法绑定后,lambda才能正确捕获外部变量形成闭包。
错误原因分析
Emacs 24及以上版本就已经支持闭包,但默认的动态绑定模式下,函数内的变量会在调用时动态查找,而不是被lambda捕获保存。你的make-callback函数里,buffer参数在动态绑定环境下不会被闭包保留,当url-retrieve异步调用回调时,buffer变量已经不存在,就会触发未定义变量的错误。
解决方法
只需要开启词法绑定即可,有两种方式:
- 如果是在文件中编写代码,在文件最顶部添加一行声明:
;; -*- lexical-binding: t -*- - 如果是在scratch缓冲区测试,先执行以下代码开启词法绑定,再重新定义你的函数:
(setq lexical-binding t)
修改后的完整代码示例
;; -*- lexical-binding: t -*- (defun make-callback (buffer) (lambda (status) (message "buffer: %s" buffer))) (defun make-rest-call () (interactive) (let* ((buffer (current-buffer)) (callback (make-callback buffer)) (url "some-url") (url-request-method "POST") (url-request-extra-headers `(("Content-Type" . "application/json"))) (url-request-data (json-encode '((key . "value"))))) ; 补全示例数据 (url-retrieve url callback)))
开启词法绑定后,make-callback返回的lambda会捕获传入的buffer变量,异步回调执行时就能正确访问到这个变量,不会再出现未定义的错误。
内容的提问来源于stack exchange,提问作者chris
相关产品推荐
相关产品推荐

