有人可以向我解释一下这个非常简单的代码段中的情况吗?(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是如何变化的。
手掌心
TA贡献1942条经验 获得超3个赞
看起来您的(let)中的'(nil)仅被评估一次。当您(设置汽车)时,每个调用都就地修改了相同的列表。如果我用(list(list))代替'(nil),则可以使(test-a)工作,尽管我认为有一种更优雅的方法。
(test-b)每次都从cons单元构建一个全新的列表,这就是为什么它工作原理不同的原因。
- 3 回答
- 0 关注
- 552 浏览
添加回答
举报
0/150
提交
取消