Emacs 24 现在有词法范围的变量。当然,它还具有动态范围的变量。既然它两者都有,我对变量何时具有哪种范围感到很困惑。有一个lexical-binding
变量控制何时启用词法绑定,我想我读过一些关于defvar
现在声明一个动态范围变量的内容,但总的来说我很迷茫。Emacs 24 的新范围规则是否有很好的解释?或者换一种说法,当我查看为 Emacs 24 编写的 Emacs Lisp 代码中的一个变量时,我如何知道该变量正在使用什么范围?
2 回答
手册是权威来源。从这里开始:
C-hig (elisp) Variable Scoping
RET
我最初在这个答案中引用了手册,但是该信息(可以追溯到 Emacs 24.0.90.1)稍微过时了。最好从 Emacs 内部阅读手册,以便信息对于您正在使用的版本是正确的。
如果你特别想在网页上阅读,当前版本是:
http ://www.gnu.org/software/emacs/manual/html_node/elisp/Variable-Scoping.html
假设正在 Emacs 中逐步评估某些代码(因为您刚刚这样做C-x C-e
,或者因为正在加载 Emacs Lisp 文件,或者因为正在运行挂钩中的函数等),并且 Emacs 即将在其中进行my-abc
评估那个代码。也许my-abc
是该代码中的局部变量,或者它未声明,或者它具有一些全局值等。无论如何,当前步骤是评估my-abc
. 那时,Emacs 只检查两件事来决定是否my-abc
使用词法范围进行评估。
Emacs 检查的第一件事是“是my-abc
一个特殊变量吗?”。(defvar my-abc ...)
如果or (defcustom my-abc ..)
or etc 在过去的任何时候运行,该问题的答案是肯定的。可能(defcustom my-abc ..)
是在加载其他一些 Emacs Lisp 文件时运行的,或者您可能评估了包含(defvar my-abc ...)
在暂存缓冲区中的一些代码,或者可能没有。如果出于某种原因答案是肯定的,那么 Emacs 此时将my-abc
使用动态范围进行评估。
如果答案是否定的,那么 Emacs 会检查第二件事,即 (A) “my-abc
我 (Emacs) 正在逐步执行的这段代码(包含 的使用)在哪里?”。这不是(B)“现在的缓冲区是什么?”。如果您刚刚在缓冲区上按下 Cx Ce foo.el
,并且如果您按下 Cx ce 的表达式包含对mah-hello
定义在中的函数的调用mah-stuff.el
,并且如果mah-hello
函数体包含对my-hello
定义在中的函数的调用my-stuff.el
,并且如果函数体my-hello
包含使用一个名为 的变量my-abc
,那么当 Emacs 最终开始执行my-hello
并即将my-abc
在那里进行评估时,当 Emacs 询问问题 A 时,它my-stuff.el
会自己回答。不是缓冲区foo.el
包含起始表达式。
然后 Emacs 询问“是my-stuff.el
一个词法范围的缓冲区,换句话说,lexical-binding
在那个缓冲区上是真的吗?”。如果是,Emacsmy-abc
使用词法范围进行评估,否则使用动态范围。
一些更新:此外,当代码被引用为数据然后传递给eval
函数时,(A)的答案将不是缓冲区。尽管如此,就好像eval
组成了一个假想的缓冲区来放置代码,并将该缓冲区的缓冲区本地值设置lexical-binding
为传递给eval
. (A) 的答案不是包含“eval”调用的缓冲区。它是虚构的缓冲区。
对于 Lisp 宏,当一些宏扩展代码正在运行时,就好像扩展代码被写入包含调用宏的代码的缓冲区。因此,在这种情况下,(A) 的答案不是定义宏的缓冲区,而是调用宏的代码所在的缓冲区。