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