(car *ll*)
and (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* http://www.lispworks.com/documentation/HyperSpec/Body/v_pr_cir.htm to 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=…
and #1#
表明sameobject 是列表的第一个和第二个元素。
如果您想要副本,请制作副本
我希望将一个新列表添加到列表列表中,例如((1 1 1) (0 0 0))
,
其中该列表集合的新头是根据
前一个头。 ……
> (push (car *ll*) *ll*)
((1 1 1) (1 1 1) (0 0 0))
你说你想添加一个new列表到列表的列表,但您没有添加new列表;你正在添加(car *ll*)
这是您一开始创建的列表(list 1 1 1)
。如果您想复制列表,则需要显式复制它,例如,使用copy-list http://www.lispworks.com/documentation/HyperSpec/Body/f_cp_lis.htm:
> (push (copy-list (car *ll*)) *ll*)
((1 1 1) (1 1 1) (0 0 0))
不要修改文字数据!
顺便说一句,您在第二个代码块中所做的实际上是未定义的行为,因为您正在修改literal list '(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))
See 我的答案 https://stackoverflow.com/a/18790523/1281433 to 意外的数据持久性 https://stackoverflow.com/q/18790192/1281433详细了解为什么这可能会出现问题。