公共Lisp中的动态绑定
这个问题是问题的延伸 我已经阅读并(希望)理解了CommonLisp(link:)中的作用域和范围的概念,但我无法理解以下三个示例。所有示例都在SBCL/Slime/Emacs中的新lisp会话上运行 示例1:打印5和5公共Lisp中的动态绑定,lisp,common-lisp,Lisp,Common Lisp,这个问题是问题的延伸 我已经阅读并(希望)理解了CommonLisp(link:)中的作用域和范围的概念,但我无法理解以下三个示例。所有示例都在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
(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
- 示例1:x是一个范围不确定的变量,在fun1中设置为5,因此fun2访问该值。这是正确的解释吗
- 示例2:x由defvar设置为100,但为什么在调用fun1时不重新设置为5?我认为绑定是在调用函数时发生的,还是在定义函数时发生的?当fun1被定义时,x似乎还没有被绑定,因此fun1中x的绑定(在词汇范围内)没有被程序的其余部分看到,然后“全局”绑定在随后的defvar中发生。函数调用中的行为x是否是由于fun1中的词法阴影,而fun2中没有动态阴影?也就是说,这里有两个不同的x实例,因为fun1首先定义了它的x,而当时没有看到“全局”x
- 示例3:此处显示,由于x是先全局设置的,fun1和fun2都引用x的同一实例,因此其值在fun1期间更新,在fun2期间也应用(均为5)?此外,当我在最后询问x的值时,我得到了100(为什么?当fun2返回5时?)
defvar
声明x
时,变量被声明为特殊变量,从现在起x
始终被视为特殊变量,并动态绑定。当你打电话时:
(fun1 5)
fun1
中的绑定是动态完成的,这意味着fun1
和fun2
的返回值都基于当前的x
动态绑定
例2:[…]即,这里有两个不同的x实例,因为fun1首先定义了它的x,而当时没有看到“全局”x
是的,但并非所有口译员都是如此(见西尔维斯特的答案)。当您定义fun1
时,x
并不特殊;这意味着此时参数x
的范围是词法的。稍后,当计算defvar
时,fun1
中x
的绑定仍然是词法绑定,因此调用fun1
不会修改全局变量x
的动态绑定
示例3:[…]此外,当我在末尾询问x的值时,我得到了100(为什么?当fun2返回5时
特殊变量的作用域是不确定的,它们随处可见,但它们的绑定具有动态范围,这意味着绑定只在建立它的形式存在时才存在
在这里,当您在顶层请求x
时,您拥有全局绑定到x
,100的值;在调用fun1
有效时,值5仅临时绑定到x
如果您使用SETF
来变异绑定,那么您可以变异全局绑定,但在函数应用或let
绑定期间不会发生这种情况
示例1:x是一个范围不确定的变量,在fun1中设置为5,因此fun2访问该值。这是正确的解释吗
主要是,让我进一步说明一下
当defvar
声明x
时,变量被声明为特殊变量,从现在起x
始终被视为特殊变量,并动态绑定。当调用:
(fun1 5)
fun1
中的绑定是动态完成的,这意味着fun1
和fun2
的返回值都基于当前的x
动态绑定
例2:[…]即,这里有两个不同的x实例,因为fun1首先定义了它的x,而当时没有看到“全局”x
是的,但并非所有口译员都是如此(见西尔维斯特的回答)。当您定义fun1
时,x
并不特殊;这意味着此时参数x
的范围是词法的。稍后,当计算defvar
时,fun1
中的x
的绑定仍然是词法的,因此调用fun1
不会修改g的动态绑定大叶变量x
示例3:[…]此外,当我在末尾询问x的值时,我得到了100(为什么?当fun2返回5时
特殊变量的作用域不确定,它们随处可见,但它们的绑定具有动态ext
(with-output-to-string (*standard-output*)
(some-function-whose-printed-output-you-want))
; ==> a string with the actual output
(defvar x 100) ; declares X to be special, globally and locally
; also sets X to 100
(defun fun1 (x) ; X is a dynamically bound variable
(print x) ; lookup of dynamic binding of X
(fun2))
(defun fun2 ()
(print x)) ; lookup of dynamic binding of X
(fun1 5)
(defun fun1 (x) ; X is a lexical local variable
(print x) ; lexical reference to X
(fun2))
(defun fun2 ()
(print x)) ; X is undeclared/undefined
; the exact behaviour is undefined in Common Lisp
; many implementations assume dynamic lookup of X
; most compilers will show a warning
; CMUCL also by default declared X globally to be special
; -> don't use this in your code
(defvar x 100) ; declares X to be special, globally and locally
; also sets X to 100
(fun1 5)
(defvar x 100) ; declares X to be special, globally and locally
; also sets X to 100
(defun fun1 (x) ; X is a dynamically bound variable
(print x) ; lookup of dynamic binding of X
(fun2))
(defun fun2 ()
(print x)) ; lookup of dynamic binding of X
(defvar x 100) ; does nothing
; -> X is already declared special
; -> X already has a value
; see also: DEFPARAMETER
(fun1 5)
x ; lookup of global (or thread local) value of X