emacs词法范围和带引号的变量名

emacs词法范围和带引号的变量名,emacs,elisp,emacs24,lexical-scope,Emacs,Elisp,Emacs24,Lexical Scope,我在试验Emacs词法范围(Emacs 24的新功能)和添加到列表之间的相互作用,发现这种相互作用令人困惑,我不知道如何理解。这里是一个简单的例子,除了我使用set而不是addtolist。(set类似于addtolist,因为它通常采用带引号的变量名) 以上代码按顺序打印“成熟苹果”、“成熟苹果”、“按设置”。第一个打印结果“成熟的苹果”与预期的词法范围(支持词法闭包)一样,这里没有什么令人惊讶的。但第二次和第三次印刷的结果令我惊讶。这就好像(set'a“by set”)只识别并影响名称a的全

我在试验Emacs词法范围(Emacs 24的新功能)和
添加到列表
之间的相互作用,发现这种相互作用令人困惑,我不知道如何理解。这里是一个简单的例子,除了我使用
set
而不是
addtolist
。(
set
类似于
addtolist
,因为它通常采用带引号的变量名)

以上代码按顺序打印“成熟苹果”、“成熟苹果”、“按设置”。第一个打印结果“成熟的苹果”与预期的词法范围(支持词法闭包)一样,这里没有什么令人惊讶的。但第二次和第三次印刷的结果令我惊讶。这就好像
(set'a“by set”)
只识别并影响名称
a
的全局绑定

这是故意的行为吗?还是这是一只虫子?如果有意,人们如何理解这种行为

我假设只要启用词法作用域,
set
就会影响全局绑定,对吗

有了
(eval'(progn…)nil)
,事情就按照动态作用域的预期运行,
(set'a…
的行为与
(setq a…
在这种情况下的行为相同。只有在同时使用词法范围和带引号的变量时,才会出现这种情况


更新:

根据手册,这似乎是一种预期行为。手册上说

在词汇绑定规则下,值单元格仅保存变量的全局值,即任何词汇绑定构造之外的值。当一个变量被词汇绑定时,局部值由词汇环境决定;如果变量的符号值单元格未赋值,则该变量可能具有局部值

等等

诸如symbol value、boundp和set等函数仅检索或修改变量的动态绑定(即其符号的值单元格的内容)


symbol value、boundp、set是通常使用带引号的变量名调用的函数(
(symbol value'var)(boundp'var)(set'var 123)
)。这些函数仅获取或设置符号的值单元格,在词汇绑定规则下,值单元格仅保存全局值。因此,在词法绑定下,使用带引号的变量只能获取或设置全局值(除非该变量是特殊变量)。尽管结果既不是词法(apple)也不是动态(banana)这一点看起来仍然很奇怪。

但代码的编写方式并不是Emacs所期望的能够编写词法作用域的程序

defvar
defconst
是将符号定义为全局变量的特殊形式,该变量可以在Lisp程序中的任意点访问

(……)

原则上,您可以使用
setq
将变量值分配给任何符号,无论它是否首先定义为变量。但是,您应该为要使用的每个全局变量编写一个变量定义;否则,如果在启用词法作用域的情况下对Lisp程序进行计算,则该程序可能无法正确运行

请注意,
symbol value
boundp
set
等函数仅检索或修改变量的动态绑定(即其符号值单元格的内容)。此外,
defun
defmacro
的主体中的代码不能引用周围的词汇变量

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

这种特殊形式是更改变量值的最常用方法。(…)符号的当前绑定已更改

(……)

功能:
设置
符号值

此函数将值放入symbol的值单元格中

(……)

当动态变量绑定生效时(默认值),
set
setq
具有相同的效果,除了
set
计算其符号参数而
setq
不计算之外。但是当一个变量被词汇绑定时,
set
会影响它的动态值,而
setq
会影响它的当前(词汇)值

如果我们添加将
a
定义为全局变量的
defvar
,我们可以看到
my-print-a
函数中对
a
的所有引用都是动态绑定的,如手册所述:


代码的编写方式与Emacs期望编写启用词法作用域的程序的方式不同

defvar
defconst
是将符号定义为全局变量的特殊形式,该变量可以在Lisp程序中的任意点访问

(……)

原则上,您可以使用
setq
将变量值分配给任何符号,无论它是否首先定义为变量。但是,您应该为要使用的每个全局变量编写一个变量定义;否则,如果在启用词法作用域的情况下对Lisp程序进行计算,则该程序可能无法正确运行

请注意,
symbol value
boundp
set
等函数仅检索或修改变量的动态绑定(即其符号值单元格的内容)。此外,
defun
defmacro
的主体中的代码不能引用周围的词汇变量

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

这种特殊形式是更改变量值的最常用方法。(…)符号的当前绑定已更改

(……)

功能:
设置
符号值

此函数将值放入symbol的值单元格中

(……)

当动态变量绑定生效时(默认),
set
具有相同的eff
(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
(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)