Common Lisp中的属性列表是指一些全局状态?

car*_*nen 5 lisp sbcl common-lisp

下面的代码z作为局部变量,但它的行为就好像它是一个全局变量:

(defun foo (m)
  (let ((z '(stuff nil)))
    (push m (getf z 'stuff))
    (print z)))

(foo 1)
(foo 2)
(foo 3)
Run Code Online (Sandbox Code Playgroud)

我希望输出是

(STUFF (1)) 
(STUFF (2)) 
(STUFF (3)) 
T
Run Code Online (Sandbox Code Playgroud)

但是当我用SBCL运行它时,我明白了

(STUFF (1)) 
(STUFF (2 1)) 
(STUFF (3 2 1)) 
T
Run Code Online (Sandbox Code Playgroud)

为什么会这样?这种行为是属性列表特有的吗?

WRe*_*ach 6

foo,z必然是文字表达'(stuff nil).该功能破坏性地改变z,从而破坏性地改变文字的价值.LISP在这种情况下的行为如何依赖于实现.某些实现将乖乖地改变文字值(如您的情况).其他实现将文字放在只读内存位置,如果您尝试修改这些文字,则会失败.

要获得所需的行为,请使用COPY-LIST以复制可以安全修改的文字:

(defun foo (m)
  (let ((z (copy-list '(stuff nil))))
    (push m (getf z 'stuff))
    (print z)))
Run Code Online (Sandbox Code Playgroud)

  • 我认为更习惯的方式是使用`LIST`,如`(let((z(list's stuff nil))))) (7认同)