我试图理解变量的动态和词法绑定(bind)。 我在浏览 SO 和一些链接时,遇到了一个问题: https://www.emacswiki.org/emacs/DynamicBindingVsLexicalBinding#toc2
我运行了这段代码:
(let ((a 1))
(let ((f (lambda () (print a))))
(let ((a 2))
(funcall f))))
预期结果:1
(并发出警告,表明第二个a
变量未使用,这是正常的)。
接下来,我尝试了:
(defvar a 99)
并重新运行第一个代码。结果是 2,正如教程所说。然后,为了进一步实验,我尝试删除动态绑定(bind)变量 a
,以再次获取 1
。
我尝试 (makunbound 'a)
甚至 (setq a 55)
(我默认尝试了这个,我认为全局词法绑定(bind)取决于实现,如果我理解的话)正确...)。 makunbound
似乎删除了该符号,但“动态绑定(bind)状态”似乎无论如何都被保存了。结果仍然是2
。
如何将 Common Lisp 重置为之前的状态(在动态绑定(bind) a
变量之前)?重新启动 SLIME 就可以解决问题,但我宁愿有一种方法以编程方式完成......
感谢您的回答。
最佳答案
没有可移植的方法来恢复
special
proclaim
化。
( CLISP 优惠
notspecial
)。
但是,您可以使用unintern
在某种程度上:它会让新代码将你的符号视为不
特殊
因为它现在是一个不同符号:
(defun test-a ()
(let ((a 1))
(let ((f (lambda () (print a))))
(let ((a 2))
(funcall f)))))
(test-a)
==> 1
(defvar a)
(test-a)
==> 2
现在,让我们尝试“恢复”defvar
:
(unintern 'a)
(test-a)
==> 2
哎呀!让我们看看:
(fdefinition 'test-a)
#<FUNCTION TEST-A NIL (DECLARE (SYSTEM::IN-DEFUN TEST-A))
(BLOCK TEST-A
(LET ((#:A 1)) (LET ((F (LAMBDA NIL (PRINT #:A)))) (LET ((#:A 2)) (FUNCALL F)))))>
你看,test-a
仍然使用旧的符号a
,它现在已被取消(因此打印为#:A
)。要返回,您需要重新 eval
defun
上面然后你就得到了
(test-a)
==> 1
再来一次!
关于common-lisp - 动态绑定(bind)变量: revert to previous state,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50191039/