2011-10-04 92 views
18

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

+2

如果您安装了Emacs 24,则可以在该信息中找到该信息。打开“Emacs Lisp”节点并点击“i”搜索索引。 –

+0

我安装了23和24,所以它有点混乱。有“Elisp”和“Elisp(emacs-snapshot)”条目。我现在看到它。另外,我有时会忘记Emacs是具有良好文档的项目之一,如果没有足够的文档,可能不是合并主要新功能的类型。 –

回答

21

该手册是权威性的资源。从这里开始:

我克(elisp) Variable ScopingRET

我原本报价在这个答案的手册,但这些信息(可以追溯到的Emacs 24.0.90.1)略有出来的日期。最好从Emacs里面阅读手册,以便所使用的版本的信息是正确的。

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

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 ce的表达式包含对mah-stuff.el中定义的名为mah-hello的函数的调用,并且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真?”。如果是,Emacs使用词法作用域评估my-abc,否则使用动态作用域。

某些更新:另外,当代码被引用为数据然后传递给eval函数时,对(A)的回答将不是缓冲区。尽管如此,eval构成了放置代码的虚拟缓冲区,并将该缓冲区的缓冲区本地值lexical-binding设置为传递给eval的第二个参数。 (A)的答案是而不是包含“eval”调用的缓冲区。这是虚构的缓冲区。

对于Lisp宏,当某些宏展开代码正在运行时,就好像展开的代码被写入包含调用该宏的代码的缓冲区。因此,在这种情况下对(A)的回答是而不是定义宏的缓冲区,而是调用宏的代码驻留的缓冲区。

+0

很好的解释。谢谢! – killdash9