在 LISP 中,我有一个传递列表的函数。我想更改此列表的元素而不更改原始列表。通常情况下,我会使用copy-list
创建我将更改的列表的本地副本,但这似乎不起作用:
CL-USER> (defun test (item)
(let ((copy (copy-list item)))
(setf (nth 0 (nth 0 (nth 0 copy))) t)
(print item)
(print copy)))
CL-USER> (defparameter item `(((NIL NIL) (NIL NIL) (NIL NIL))
((NIL NIL NIL) (NIL NIL NIL))
((3 3) (NIL NIL))))
CL-USER> (test item)
(((T NIL) (NIL NIL) (NIL NIL)) ((NIL NIL NIL) (NIL NIL NIL)) ((3 3) (NIL NIL)))
(((T NIL) (NIL NIL) (NIL NIL)) ((NIL NIL NIL) (NIL NIL NIL)) ((3 3) (NIL NIL)))
(((T NIL) (NIL NIL) (NIL NIL)) ((NIL NIL NIL) (NIL NIL NIL)) ((3 3) (NIL NIL)))
CL-USER> item
(((T NIL) (NIL NIL) (NIL NIL)) ((NIL NIL NIL) (NIL NIL NIL)) ((3 3) (NIL NIL)))
正如你所看到的,值item
被更改为test
即使我将列表复制到本地变量中并更改了本地副本。这似乎是使用的症状nth
。如果我使用一次调用car
而不是重复调用nth
,该函数按预期工作,并且item
调用后没有变化。
为什么nth
像这样的行为我该如何继续使用nth
不改变传递给的值test
?
我正在使用 Common Lisp。
简短回答:使用 cl:copy-tree
您可能想复制整棵树复制树。所制作的副本复制列表只产生新的“骨干”;你会得到一个新列表,但是随着same元素。复制树将复制构成树的所有 cons-tree 结构。
长答案:列表结构与树结构
文档中引用了此处的背景。来自超规范:
功能复制列表
只有列表结构列表被复制;的要素
结果列表与给定的相应元素相同
列表。
该词汇表条目为列表结构很重要:
列表结构(列表的)组成列表的一组 cons。
请注意,虽然每个此类缺点的汽车组件都是
列表结构,作为列表元素的对象(即
列表中每个缺点的汽车的对象)不是
它们本身是列表结构的一部分,即使它们是conses,除了
在列表实际上包含其之一的(循环)情况下
尾巴作为一个元素。 (列表的列表结构有时是
重复地称为其“顶级列表结构”
强调作为列表元素的任何 cons 都不是
涉及。)
作为一个非常简单的例子,我们可以利用以下事实:*打印圆圈*将向我们展示常见的子结构:
CL-USER> (setf *print-circle* t)
T
CL-USER> (let ((l '((a b c) (d e f))))
(list l (copy-list l)))
;=> ((#1=(A B C) #2=(D E F)) (#1# #2#))
CL-USER> (let ((l '((a b c) (d e f))))
(list l (copy-tree l)))
;=> (((A B C) (D E F)) ((A B C) (D E F)))
HyperSpec 条目位于复制树没有链接到树结构,但是有is词汇表条目:
树结构名词(一棵树的)组成的cons的集合
树。请注意,虽然每个此类缺点的汽车组件都是
在树结构中,对象是每个 cons 的汽车
树中的内容本身并不是其树结构的一部分,除非它们
也是缺点。
第二句话有点奇怪,但它可能只是作为最低限度调整的复制和粘贴而存在的列表结构入口。看我的答案 to Lisp中树结构的定义了解更多相关信息。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)