在Lisp中复制和修改列表列表的头部

时间:2014-03-11 23:08:02

标签: list lisp sbcl

我正在学习Lisp。我希望在列表列表中添加一个新列表,比如说((1 1 1)(0 0 0)),其中此列表集合的新头部是根据前一个头部计算的。

这是我尝试过的,在Slimv的REPL环境中使用sbcl:

> (defvar *ll* (list (list 1 1 1) (list 0 0 0)))
*LL*
> *ll*
((1 1 1) (0 0 0))
> (push (car *ll*) *ll*)
((1 1 1) (1 1 1) (0 0 0))
> (setf (nth 2 (car *ll*)) 2)
2
> *ll*
((1 1 2) (1 1 2) (0 0 0))

如上所示,我只想修改第一个列表的最后一个元素,但不知何故,第二个列表的最后一个元素也被修改了。

我注意到,如果我推入一个全新的列表,那么结果就不同了:

> (defvar *lll* (list (list 1 1 1) (list 0 0 0)))
*LLL*
> (push '(1 1 1) *lll*)
((1 1 1) (1 1 1) (0 0 0))
> (setf (nth 2 (car *lll*)) 2)
2
> *lll*
((1 1 2) (1 1 1) (0 0 0))

我想知道导致这些不同结果的原因,以及如何实现"将新列表添加到列表列表的结果,其中结果列表集合的新头部基于计算以前的头。"谢谢!

1 个答案:

答案 0 :(得分:1)

(car *ll*)(cadr *ll*)是相同的列表

> (defvar *ll* (list (list 1 1 1) (list 0 0 0)))
*LL*
> *ll*
((1 1 1) (0 0 0))
> (push (car *ll*) *ll*)
((1 1 1) (1 1 1) (0 0 0))
> (setf (nth 2 (car *ll*)) 2)
2
> *ll*
((1 1 2) (1 1 2) (0 0 0))
     

如上所示,我只想修改第一个元素   列表,但不知何故,第二个列表的最后一个元素也是   改变。

那里只有一个对象,你修改了它。它与你有某种结构化数据类型(实际上,什么是cons单元格,只有两个字段的结构化数据类型)并没有什么不同。如果您有一个人员列表,然后再将第一个人添加到列表中,那么仍然只有一个人;这个人只出现在名单中的两个地方。如果您更改此人的姓名,您将在两个地方都看到它。如果您将*print-circle*设置为t,则实际上可以看到共享结构。

CL-USER> (defvar *ll* (list (list 1 1 1) (list 0 0 0)))
*LL*
CL-USER> *ll*
((1 1 1) (0 0 0))
CL-USER> (push (car *ll*) *ll*)
((1 1 1) (1 1 1) (0 0 0))
CL-USER> *ll*
((1 1 1) (1 1 1) (0 0 0))
CL-USER> (setf *print-circle* t)
T
CL-USER> *ll*
(#1=(1 1 1) #1# (0 0 0))

使用#1=…#1#的表示法表示相同的对象是列表的第一个和第二个元素。

如果您想要副本,请复制

  

我希望在列表列表中添加一个新列表,比如((1 1 1) (0 0 0)),   这个列表集合的新头部是基于的   前任主管。 ...

> (push (car *ll*) *ll*)
((1 1 1) (1 1 1) (0 0 0))

您说要将列表添加到列表列表中,但是您没有添加列表;您正在添加(car *ll*),这是您在(list 1 1 1)开头创建的列表。如果您要复制列表,则需要明确复制,例如copy-list

> (push (copy-list (car *ll*)) *ll*)
((1 1 1) (1 1 1) (0 0 0))

不要修改文字数据!

另外,您在第二个代码块中执行的操作实际上是未定义的行为,因为您正在修改文字列表'(1 1 1)

> (defvar *lll* (list (list 1 1 1) (list 0 0 0)))
*LLL*
> (push '(1 1 1) *lll*)            ; '(1 1 1) is literal data.
((1 1 1) (1 1 1) (0 0 0))
> (setf (nth 2 (car *lll*)) 2)     ; (car *lll*) is literal data, and you're modifying it!
2
> *lll*
((1 1 2) (1 1 1) (0 0 0))

请参阅my answerUnexpected persistence of data了解更多有关此问题的原因。