我试图了解变量的动态和词汇绑定。 当我在这个问题上遇到问题时,我正在浏览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,就像教程说的那样。然后,为了进一步实验,我尝试删除动态绑定变量a
,再次获取1
。
我尝试(makunbound 'a)
甚至(setq a 55)
(我默认尝试过这个,我认为如果我理解正确的话,全局词汇绑定依赖于实现......)。 makunbound
似乎删除了符号,但是"动态绑定状态"无论如何似乎都得救了。结果仍为2
。
如何将Common Lisp重置为先前的状态(在动态绑定a
变量之前)?重启SLIME可以做到这一点,但我宁愿有办法以编程方式做到这一点......
感谢您的回答。
答案 0 :(得分:2)
没有便携式方式来还原
special
proclaim
通货膨胀。
(CLISP提供
notspecial
)。
但是,您可以使用unintern
在某种程度上:它会使 new 代码将您的符号视为不符合
special
因为它现在是不同的符号:
(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
再次!