ccQ*_*ein 2 lisp common-lisp dynamic-binding
我只是在我的Common Lisp代码遇到异常情况时,我想测试locally和declare:
(defvar test-out 2) ;; make a dynamic variable
;; function below just simply re-write from locally doc
(defun test (out)
(declare (special out))
(let ((out 1))
(print out) ;; => 1
(print (locally (declare (special out)) out)))) ;; => 2
;; when argument has same name as outside dynamic variable
(defun test1 (test-out)
(declare (special test-out))
(let ((test-out 1))
(print test-out) ;; => 1
(print (locally (declare (special test-out)) test-out)))) ;; => also 1
Run Code Online (Sandbox Code Playgroud)
我知道动态变量的正确名称应该是*test-out*,但我认为这只是为了程序员方便地告诉动态变量。
我对test1函数有点困惑,看起来好像locally declare没有指向test-out外部的动态变量。
谁能向我解释test1函数的行为?谢谢
更新:
(defvar test-out-1 3),像这样调用(test1 test-out-1),仍然得到打印结果1和1。test1从的说法名字test-out来test-out1,重新编译test1和问题就消失了,打印出来的结果1和2我打电话(test1 test-out)。(defvar test-out 2)为(defvar test-out-1 2)(更改动态变量名称)。然后重新编译整个文件(test-out这次没有调用任何动态变量,并且test1参数的名称为test-out),问题消失了。(defvar test-out 2)和(test1 test-out)。这次,它打印出正确的答案:1和2。test1一遍,然后再运行(test1 test-out),它打印出来1,并1再次,问题再次出现。如果我猜对了,则test1出于某种原因,在编译时,其参数名称会连接到dynamic变量test-out。这就是为什么我什至在调用不同值时都会收到错误结果的原因,但是,当我在重新编译测试之前test1使用不同的参数名称或干净的动态变量test-out重新编译时,问题会自行解决。
如果是这样,我仍然不明白为什么编译功能会在环境中受到动态变量的影响。
DEFVAR声明一个特殊的变量-这意味着它们在绑定时将使用动态绑定,访问此类变量将寻找动态绑定。在全球和所有绑定级别。现在和将来。
从那时起,新代码中该变量的所有使用和绑定将自动声明为特殊。甚至是本地LET绑定。在所有级别上。没有办法将其声明为非特殊。因此,test1现在不再需要函数中的局部特殊声明,因为它已经被声明为特殊。现在,即使没有显式声明,它的每次使用或绑定都在使用动态绑定。
这也是为什么将任何变量DEFVAR或DEFPARAMETER变量写为的原因*variablename*,以防止意外地将所有具有相同名称的变量声明为特殊变量。
避免:
(defvar x 10) ; here X is explicitly declared special
(defun foo (x) ; here X is implicitly declared special
(let ((x ...)) ; here X is implicitly declared special
...))
Run Code Online (Sandbox Code Playgroud)
做:
(defvar *x* 10) ; here *X* is declared special
(defun foo (x) ; here X is lexical
(let ((x ...)) ; here X is lexical
...))
Run Code Online (Sandbox Code Playgroud)