问题描述
下面的代码将z
作为局部变量,但其行为就像是全局变量一样:
The code below has z
as a local variable, yet it behaves as if it is a global:
(defun foo (m)
(let ((z '(stuff nil)))
(push m (getf z 'stuff))
(print z)))
(foo 1)
(foo 2)
(foo 3)
我希望输出是
(STUFF (1))
(STUFF (2))
(STUFF (3))
T
但是当用SBCL运行它时,我看到了
but when running it with SBCL I see
(STUFF (1))
(STUFF (2 1))
(STUFF (3 2 1))
T
为什么会这样?这种行为是属性列表所特有的吗?
Why is this the case? Is this behaviour peculiar to property lists?
推荐答案
在foo
中,z
绑定到文字表达式'(stuff nil)
.该函数破坏性地更改了z
,从而破坏性地更改了文字的值.在这种情况下,LISP的行为方式取决于实现.有些实现会乖乖地更改文字值(如您的情况).其他实现将文字放在只读的内存位置,如果您尝试修改这些文字,将失败.
In foo
, z
is bound to the literal expression '(stuff nil)
. The function destructively alters z
, thus destructively changing the value of the literal. How LISP behaves in circumstances like this is implementation-dependent. Some implementations will obediently alter the literal value (as in your case). Other implementations place literals in read-only memory locations and will fail if you attempt to modify those literals.
要获得所需的行为,请使用COPY-LIST
制作可以安全修改的文字副本:
To get the desired behaviour, use COPY-LIST
to make a copy of the literal that can be safely modified:
(defun foo (m)
(let ((z (copy-list '(stuff nil))))
(push m (getf z 'stuff))
(print z)))
这篇关于Common Lisp中的属性列表是否引用某些全局状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!