为何Let Over Lambda在Emacs Lisp中无法形成词法闭包?
为什么Emacs Lisp中无法形成Common Lisp那样的词法闭包?
这核心是作用域规则的差异:
Emacs Lisp的默认作用域是动态作用域
早期Emacs Lisp完全基于动态作用域设计,后来才逐步添加词法作用域支持,但它并非默认开启状态。用defun定义函数时,默认会在全局动态作用域中创建,不会捕获let绑定的局部变量——当你调用g时,Emacs Lisp会去全局动态环境查找x,自然找不到,因此报错。Common Lisp默认是词法作用域
Common Lisp从设计之初就默认采用词法作用域,let内部定义的defun会自然捕获外部的词法变量,形成闭包,调用时能正确读取x的值。
解决方法
要在Emacs Lisp中实现类似的闭包效果,有两种可行方式:
- 开启文件级词法作用域:在Emacs Lisp文件开头添加注释标记,让整个文件启用词法作用域:
;; -*- lexical-binding: t -*- (let ((x 7)) (defun g (y) (* y x))) (g 16) ; 此时会返回112,正常运行
- 用
lexical-let兼容旧版本:如果需要兼容不支持lexical-binding的旧版Emacs,可以用lexical-let创建词法绑定的变量:
(lexical-let ((x 7)) (defun g (y) (* y x))) (g 16) ; 同样返回112
内容的提问来源于stack exchange,提问作者Samantha Atkins
相关产品推荐
相关产品推荐

