Emacs 24中变量作用域的新规则是什么?

时间:2011-10-04 22:41:38

标签: emacs elisp lexical-scope dynamic-scope emacs24

Emacs 24现在具有词法范围的变量。当然,它还具有动态范围的变量。既然它有两者,我很困惑变量什么时候会有哪种范围。有一个lexical-binding变量控制何时启用词法绑定,我想我现在读了一些关于defvar声明动态范围变量的内容,但总的来说我很丢失。在Emacs 24的新范围规则中,是否有一个很好的解释?换句话说,当我查看为Emacs 24编写的Emacs Lisp代码中的变量时,如何判断变量使用的范围?

2 个答案:

答案 0 :(得分:21)

手册是最终来源。从这里开始:

C-h i g (elisp) Variable Scoping RET

我最初在这个答案中引用了手册,但是这些信息(可以追溯到Emacs 24.0.90.1)有点过时了。最好从Emacs内部阅读手册,以便信息对于您正在使用的版本是正确的。

如果您特别想在网页上阅读,目前的版本是:
http://www.gnu.org/software/emacs/manual/html_node/elisp/Variable-Scoping.html

答案 1 :(得分:3)

假设有些代码正在Emacs中逐步进行评估(或者因为您刚刚执行C-x C-e或者因为正在加载Emacs Lisp文件或因为正在运行钩子中的函数等),并且Emacs即将评估该代码中的my-abc。也许my-abc是该代码中的局部变量,或者它可能未被声明,或者它可能具有某种全局值等。无论如何,当前步骤是对my-abc的评估。那时,Emacs只检查两件事来决定是否使用词法范围评估my-abc

Emacs检查的第一件事是“my-abc是一个特殊变量?”。如果(defvar my-abc ...)(defcustom my-abc ..)等在过去的任何时间点运行,那么该问题的答案是肯定的。也许(defcustom my-abc ..)在加载其他一些Emacs Lisp文件时运行,或者你可能在暂存缓冲区上评估了一些包含(defvar my-abc ...)的代码,或者可能没有。如果答案是肯定的,那么Emacs此时将使用动态范围评估my-abc

如果答案是否定的,那么Emacs会检查第二件事,即(A)“我(Emacs)正在逐步执行此代码(包含my-abc的使用)?”。这不是(B)“现在的当前缓冲区是什么?”。如果您只是在缓冲区上按Cx Ce,请说foo.el,如果您按下Cx的表达式包含对mah-hello中定义的名为mah-stuff.el的函数的调用,如果mah-hello函数体包含对名为my-hello的函数的调用,该函数在my-stuff.el中定义,如果my-hello的函数体包含使用名为{{1}的变量然后,当Emacs最终执行my-abc然后即将评估my-hello时,当Emacs询问问题A时,它会回答my-abc。不是包含起始表达式的缓冲区my-stuff.el

然后Emacs询问“foo.el是一个词法范围的缓冲区,换句话说,该缓冲区上的my-stuff.el是否为真?”。如果是,则Emacs使用词法范围评估lexical-binding,否则使用动态范围。

一些更新:此外,当代码被引用为数据然后传递给my-abc函数时,(A)的答案将不是缓冲区。仍然,好像eval组成了一个假想的缓冲区来放置代码,并将该缓冲区的缓冲区本地值eval设置为传递给lexical-binding的第二个参数。 (A)的答案是包含`eval'调用的缓冲区。它是虚构的缓冲区。

对于Lisp宏,当运行一些宏扩展代码时,就好像扩展代码被写入包含调用宏的代码的缓冲区一样。因此,在这种情况下(A)的答案是定义宏的缓冲区,而是调用宏的代码所在的缓冲区。