emacs的词法作用域和引用变量名(emacs lexical scoping and quoted

2019-10-17 04:15发布

我和词法作用域(Emacs的24的新功能)的Emacs之间的相互作用和试验add-to-list ,发现相互作用混乱,我不知道如何来理解它。 下面是一个小例子,我除了使用set ,而不是add-to-list 。 ( set类似于add-to-list中,这通常需要引用变量名)

(eval
 '(progn
    (setq a "global")
    (let ((a "apple"))
      (defun my-print-a ()
        (print a)
        (set 'a "by set")
        (print a))
      (setq a "mature apple"))
    (let ((a "banana"))
      (my-print-a))
    (print a))
 t) ;; t for lexical scoping

上面的代码打印,以“成熟的苹果”,“苹果成熟”,“被设为”。 第一个打印结果,“成熟的苹果”,为预期词法作用域(与词法闭包支持),没什么好惊讶在这里看到。 但第二和第三打印的结果令我感到诧异。 这是因为如果(set 'a "by set")只承认和影响名称的全局绑定a

这是一个预期的行为? 或者这是一个错误? 如果打算,怎样才能实现这一行为有意义吗?

我是正确的假设,它总是在全球约束力的set只要词汇范围是上影响?

随着(eval '(progn ...) nil) ,工作的事情如预期的动态范围界定和行为(set 'a ...)是相同的(setq a ...)在这种情况下。 只有当一个使用词法作用域和引用变量一起,这个疑难杂症显示出来。


更新:

它似乎根据手册是一种预期行为。 在虚空变量 ,手册说

在词法约束力的规则,该值仅细胞保持可变的全球价值,即任何词汇结合构建之外的价值。 当变量词法束缚,局部值是由词法环境确定; 如果其符号价值细胞是未分配的变量可能有局部值。

和词法绑定

像符号值,boundp,和设置的功能仅检索或修改变量的动态结合(即它的符号的值单元格的内容)。

符号值,boundp,集通常与引用变量名调用的函数( (symbol-value 'var) (boundp 'var) (set 'var 123) 这些功能仅获取或设置一个符号的值单元格,并在词汇约束力的规则,值单元格只包含全局值。 所以在词法绑定,使用引用变量的唯一获取或设置全局值(除非该变量是一个特殊的变量)。 虽然它似乎仍然在这奇怪的结果既不词汇(苹果),也不是动态的(香蕉)。

Answer 1:

代码不写在Emacs的预计要写入的词汇启用作用域的程序的方式。

http://www.gnu.org/software/emacs/manual/html_node/elisp/Definitions.html

defvardefconst是定义一个符号作为可以在任何点在一个Lisp程序访问的全局变量-变量特殊形式。

(......)

原则上,你可以一个变量赋值给任何符号setq ,是否不是已首先被定义为一个变量。 但是,你应该写的,你要使用的每个全局变量变量定义; 否则,你的Lisp程序可能无法正确如果启用了词法范围评估行动。

http://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html

请注意,功能,如symbol-valueboundp ,和set仅检索或修改变量的动态结合(即它的符号的值单元格的内容)。 此外,在体内的代码defundefmacro不能引用周围词法变量。

http://www.gnu.org/software/emacs/manual/html_node/elisp/Setting-Variables.html

特殊形式: setq [ 符号 ] ...

这种特殊形态改变一个变量的值的最常用的方法。 (......)符号的结合电流变化。

(......)

功能: set 符号

该功能使价值 符号的值单元格。

(......)

当动态变量绑定是有效(缺省值), set具有相同的效果setq ,除了这一事实set而评估其符号参数setq没有。 但是,当一个变量词法束缚, set影响其动态值,而setq影响其电流(词汇)值。

如果再加上defvar定义a作为一个全局变量,我们可以看到,所有的引用amy-print-a函数变成是动态绑定的手册说明

(eval
 '(progn
    (defvar a nil)
    (setq a "global")
    (let ((a "apple"))
      (defun my-print-a ()
        (print a)                       ; "banana"
        (set 'a "by set")              
        (print a))                      ; "by set"
      (setq a "mature apple"))
    (let ((a "banana"))
      (my-print-a))
    (print a))                          ; "global"
 t)


文章来源: emacs lexical scoping and quoted variable name