Common Lisp中的属性列表是否引用某些全局状态? [英] Do property lists in Common Lisp refer to some global state?

查看:54
本文介绍了Common Lisp中的属性列表是否引用某些全局状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的代码将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中的属性列表是否引用某些全局状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆