common-lisp - 动态绑定(bind)变量: revert to previous state

标签 common-lisp

我试图理解变量的动态和词法绑定(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/

相关文章:

lisp - 什么情况需要用let代替let*?

tabs - Common-Lisp 以函数格式打印制表符

common-lisp - 如何在 Common Lisp 中进行基于图像的开发?

oop - 当第一个参数为 nil 时无法调用方法?

lambda - 这段 Lisp 代码是什么意思?

lisp - 从 s 表达式创建 lambda

common-lisp - 如何简洁地映射列表列表?

common-lisp - 循环宏中的 "for"和 "as"关键字有什么区别吗?

struct - Common Lisp 按顺序处理结构槽

list - 使用 Common Lisp 删除多级列表中的重复项