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