词法作用域(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))
89

CL-USER> (progn
       (setf r 66)
       (foo))
66

原文地址:https://www.cnblogs.com/flowjacky/p/2834803.html