为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕娘9325324 2019-11-19 14:41:40
有人可以向我解释一下这个非常简单的代码段中的情况吗?(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等同?
查看完整描述

3 回答

?
MMTTMM

TA贡献1869条经验 获得超4个赞

我发现罪魁祸首的确是“引用”。这是它的文档字符串:


返回参数,不对其求值。


...


警告:`quote'不会构造其返回值,而只是返回由Lisp读取器预先构造的值


...


报价应保留给不会被副作用修改的常量,除非您喜欢自修改代码。


为了方便我也改写了


(setq test-a 

      (lambda () ((lambda (x) (setcar x (cons 1 (car x))) x) (quote (nil)))))

然后用


(funcall test-a)

看看'test-a是如何变化的。


查看完整回答
反对 回复 2019-11-19
?
手掌心

TA贡献1942条经验 获得超3个赞

看起来您的(let)中的'(nil)仅被评估一次。当您(设置汽车)时,每个调用都就地修改了相同的列表。如果我用(list(list))代替'(nil),则可以使(test-a)工作,尽管我认为有一种更优雅的方法。


(test-b)每次都从cons单元构建一个全新的列表,这就是为什么它工作原理不同的原因。


查看完整回答
反对 回复 2019-11-19
  • 3 回答
  • 0 关注
  • 522 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信