词法作用域(lexical scope) && 动态作用域(dynamic scope)
有词法作用域的变量叫词法变量(lexical variable)。
在词法作用域下,一个符号参照到语境中符号名字出现的地方(可以理解为参照到定义)。局部变量缺省有着词法作用域。
eg:
CL-USER> (let ((x 50))
(defun foo ()
x))
FOO
CL-USER> (foo)
50
CL-USER> (let ((x 80))
(foo))
;Compiler warnings :
; In an anonymous lambda form: Unused lexical variable X
50
有动态作用域的变量叫特别变量(special variable)。
(PS.special宣告是独一无二的,因为它可以改变程序的行为。所有其它的宣告只是给编译器的建议;他们或许可以让一个程序运行得更快,但他们不会改变程序的行为。)
而动态作用域,我们在环境中函数被调用的地方寻找一个变量(可以理解为参照到调用)。全局变量有着动态作用域。
要使一个变量是动态作用域的,我们需要在任何它出现的语境中宣告它是special,如:
CL-USER> (let ((z 12))
(defun foo ()
(declare (special z))
z))
;Compiler warnings :
; In an anonymous lambda form: Unused lexical variable Z
FOO
CL-USER> (let ((z 19))
(declare (special z))
(foo))当然全局变量就不需要显著来说明了:
CL-USER> (progn
(setf r 99)
(defun foo ()
r))
;Compiler warnings :
; In FOO: Undeclared free variable R
FOO
CL-USER> (foo)
99
CL-USER> (setf r 95)
95
CL-USER> (foo)
95
CL-USER> (let ((r 89))
(foo))
;Compiler warnings :
; In an anonymous lambda form: Unused lexical variable R
95
CL-USER> (let ((r 89))
(declare (special r))
(foo))
89CL-USER> (progn
(setf r 66)
(foo))
66