为什么在这种情况下,elisp局部变量会保留其值?

有人可以向我解释一下这个非常简单的代码段中的情况吗?


(defun test-a ()

  (let ((x '(nil)))

    (setcar x (cons 1 (car x)))

    x))

(test-a)首次通话时,我得到了预期的结果:((1))。但让我吃惊,称这是一次,我得到((1 1)),((1 1 1))等等。为什么会这样呢?我期望(test-a)总是回来是错误的((1))吗?另请注意,在重新评估的定义之后test-a,返回结果将重置。


还请考虑此功能按我的预期工作:


(defun test-b ()

  (let ((x '(nil)))

    (setq x (cons (cons 1 (car x)) 

                  (cdr x)))))

(test-b)总是返回((1))。为什么不test-a和test-b等同?


慕娘9325324
浏览 526回答 3
3回答

MMTTMM

我发现罪魁祸首的确是“引用”。这是它的文档字符串:返回参数,不对其求值。...警告:`quote'不会构造其返回值,而只是返回由Lisp读取器预先构造的值...报价应保留给不会被副作用修改的常量,除非您喜欢自修改代码。为了方便我也改写了(setq test-a       (lambda () ((lambda (x) (setcar x (cons 1 (car x))) x) (quote (nil)))))然后用(funcall test-a)看看'test-a是如何变化的。

手掌心

看起来您的(let)中的'(nil)仅被评估一次。当您(设置汽车)时,每个调用都就地修改了相同的列表。如果我用(list(list))代替'(nil),则可以使(test-a)工作,尽管我认为有一种更优雅的方法。(test-b)每次都从cons单元构建一个全新的列表,这就是为什么它工作原理不同的原因。
打开App,查看更多内容
随时随地看视频慕课网APP