这个问题是Common Lisp作用域的扩展(动态vs词汇)
我已经阅读并(希望)理解了Common Lisp中的作用域和范围的概念(链接:https : //www.cs.cmu.edu/Groups/AI/html/cltl/clm/node43.html),但是我是无法理解以下三个示例。所有示例都在SBCL / Slime / Emacs中的全新Lisp会话上运行。
示例1:打印5和5
(defvar x 100)
(defun fun1 (x)
(print x)
(fun2))
(defun fun2 ()
(print x))
(fun1 5)
示例2:打印5和100
(defun fun1 (x)
(print x)
(fun2))
(defun fun2 ()
(print x))
(defvar x 100)
(fun1 5)
示例3:打印5&5&100
(defvar x 100)
(defun fun1 (x)
(print x)
(fun2))
(defun fun2 ()
(print x))
(defvar x 100)
(fun1 5)
x
我知道为什么fun1总是打印5(由于词法范围,但是如果我错了,请更正)。我不明白的是,为什么fun2在示例1中打印5,在示例2中打印100,然后在示例3中再次打印5?
它与Guy Steel的Common Lisp书中的以下摘录有关,但我无法理解:
“使用词法作用域的结构在每次执行时都会为每个已建立的实体有效地生成一个新名称。因此,不会发生动态阴影(尽管可能会出现词法阴影)。当涉及动态范围时,这一点尤其重要。”
以下陈述是否总是正确的(来源:https : //courses.engr.illinois.edu/cs421/sp2010/lectures/dynamicscope.pdf):
Lisp中的绑定规则是这样的:名称的使用绑定到该名称的最新声明,该声明仍然有效。
我已经开始理解其中的某些部分,但是无法对这三个部分进行全面的了解,因此,如果您能提供帮助,那将非常有帮助。
示例1:x(范围不确定的变量)在fun1中设置为5,因此fun2访问此值。这是正确的解释吗?
通常,让我对此进行扩展。
当x
被宣布defvar
,该变量被声明为特殊的,从现在开始x
是始终被视为一个特殊的变量,并动态绑定。你打电话的时候:
(fun1 5)
结合中fun1
是动态的,这意味着双方的返回值fun1
,并fun2
基于当前动态结合x
。
示例2:即,这里有x的两个不同实例,因为fun1首先定义了它的x,但当时没有看到“全局” x。
是的,但并非所有的口译员都这样(请参见Sylwester的答案)。当您定义时fun1
,x
并不特别。这意味着此时参数的范围x
是词法。稍后,当defvar
被求值时,x
in的绑定fun1
仍然是词法的,因此调用fun1
不会修改全局变量的动态绑定x
。
示例3:[...]此外,当我要求最后的x值时,我得到100(为什么?当fun2返回5时?
特殊变量的范围是不确定的,它们在任何地方都是可见的,但是它们的绑定具有动态范围,这意味着绑定的寿命只有建立它的形式。
在这里,当您x
在顶层请求时,您具有全局绑定到的值x
,100;值5仅x
在调用有效时临时绑定fun1
。
如果您曾经SETF
更改了绑定,则可以更改全局绑定,但是在函数应用程序或let
绑定期间不会发生这种情况。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句