gpt4 book ai didi

emacs - 为什么 elisp 局部变量在这种情况下保持其值?

转载 作者:太空宇宙 更新时间:2023-11-03 18:32:57 25 4
gpt4 key购买 nike

有人可以向我解释这个非常简单的代码片段中发生了什么吗?

(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-atest-b 不等价?

最佳答案

坏事

test-a自修改代码。这极其危险。虽然 变量 xlet 形式的末尾消失了,但它的初始值 仍然存在于函数对象中,这就是您要修改的值。请记住,在 Lisp 中 a function is a first class object ,它可以传递(就像数字或列表一样),有时,修改。这正是您在这里所做的:x 的初始值是函数对象的一部分,您正在修改它。

让我们实际看看发生了什么:

(symbol-function 'test-a)
=> (lambda nil (let ((x (quote (nil)))) (setcar x (cons 1 (car x))) x))
(test-a)
=> ((1))
(symbol-function 'test-a)
=> (lambda nil (let ((x (quote ((1))))) (setcar x (cons 1 (car x))) x))
(test-a)
=> ((1 1))
(symbol-function 'test-a)
=> (lambda nil (let ((x (quote ((1 1))))) (setcar x (cons 1 (car x))) x))
(test-a)
=> ((1 1 1))
(symbol-function 'test-a)
=> (lambda nil (let ((x (quote ((1 1 1))))) (setcar x (cons 1 (car x))) x))

好的

test-b 返回一个新的 cons 单元,因此是安全的。 x 的初始值永远不会被修改。 (setcar x ...)(setq x ...)的区别在于前者修改了已经存在的object变量 x 而后者在 x存储一个对象。区别类似于 x.setField(42)C++ 中的 x = new MyObject(42)

底线

一般情况下最好治疗quoted '(1) 之类的数据作为常量 - 不要修改它们:

quote returns the argument, without evaluating it. (quote x) yields x.Warning: quote does not construct its return value, but just returnsthe value that was pre-constructed by the Lisp reader (see info nodePrinted Representation). This means that (a . b) is notidentical to (cons 'a 'b): the former does not cons. Quoting shouldbe reserved for constants that will never be modified by side-effects,unless you like self-modifying code. See the common pitfall in infonode Rearrangement for an example of unexpected results whena quoted object is modified.

如果需要modify a list ,使用 listconscopy-list 而不是 quote 创建它。

参见 more examples .

PS1。这已在 Emacs 上重复.

PS2。另见 Why does this function return a different value every time?对于相同的 Common Lisp 问题。

PS3。另见 Issue CONSTANT-MODIFICATION .

关于emacs - 为什么 elisp 局部变量在这种情况下保持其值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16670989/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com