在LISP中更改列表的副本 [英] Changing copies of lists in LISP

查看:91
本文介绍了在LISP中更改列表的副本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在LISP中,我有一个传递列表的函数.我想在不更改原始列表的情况下更改此列表的元素.通常,我将使用copy-list创建将要更改的列表的本地副本,但这似乎不起作用:

In LISP, I have a function that is passed a list. I would like to change an element of this list without changing the original list. Normally, I would use copy-list to create the local copy of the list which I will change, but this doesn't seem to be working:

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在调用后保持不变.

As you can see, the value of item was changed by test even though I copied the list into a local variable and changed the local copy. This seems to be a symptom of using nth. If I use a single call of car rather than the repeated call to nth, the function works as expected and the item is unchanged after the call.

为什么nth的行为如此,如何在不更改传递给test的值的情况下继续使用nth?

Why does nth behave like this and how can I continue to use nth without altering the value passed to test?

我正在使用Common Lisp.

I am using Common Lisp.

推荐答案

简短答案:使用cl:copy-tree

您可能要使用 复制树 . 副本列表制作的副本只会生成新的主干";您会得到一个新列表,但带有 same 元素. Copy-tree (复制树)将复制组成该树的所有cons-tree结构.

Short answer: use cl:copy-tree

You probably want to copy the whole tree with copy-tree. The copy made by copy-list only generates new "backbone"; you get a new list, but with the same elements. Copy-tree will copy all the cons-tree structure that makes up the tree.

文档中引用了这里的背景.从HyperSpec中:

The background here is referenced in the documentation. From the HyperSpec:

功能副本列表

仅复制列表的列表结构;的要素 结果列表与给定的相应元素相同 列表.

Function COPY-LIST

Only the list structure of list is copied; the elements of the resulting list are the same as the corresponding elements of the given list.

列表结构的词汇表条目很重要:

That glossary entry for list structure is important:

列表结构(列表中的)构成列表的一组cons. 请注意,虽然每个这样的缺点的汽车组成部分是 列表结构,即作为列表元素的对象(即 列表中每个缺点的汽车的对象)不是 本身就是其列表结构的一部分,即使它们很简单,但 在(循环)情况下,列表实际上包含其中之一 尾巴作为元素. (列表的列表结构有时是 按顺序冗余地称为顶级列表结构" 强调列表中的任何要素都不是 参与进来.)

list structure n. (of a list) the set of conses that make up the list. Note that while the car component of each such cons is part of the list structure, the objects that are elements of the list (i.e., the objects that are the cars of each cons in the list) are not themselves part of its list structure, even if they are conses, except in the (circular) case where the list actually contains one of its tails as an element. (The list structure of a list is sometimes redundantly referred to as its "top-level list structure" in order to emphasize that any conses that are elements of the list are not involved.)

作为一个非常简单的示例,我们可以利用以下事实: * print-circle * 将向我们展示常见的子结构:

As a very simple example, we can exploit the fact that *print-circle* will show us common substructure:

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条目未链接到树结构,但是有 个词汇表条目:

The HyperSpec entry on copy-tree doesn't link to tree structure, but there is a glossary entry:

树结构 n. (一棵树的)构成 树.请注意,虽然每个这样的缺点的汽车组成部分都是 的结构,是每个缺点的汽车的对象 除非它们在树中本身不是树结构的一部分 也是有问题的.

tree structure n. (of a tree) the set of conses that make up the tree. Note that while the car component of each such cons is part of the tree structure, the objects that are the cars of each cons in the tree are not themselves part of its tree structure unless they are also conses.

第二句话有点奇怪,但它可能只是作为对 list结构条目的最小调整复制和粘贴而存在的.请参阅我的答案的定义Lisp中的树形结构,对此有更多了解.

That second sentence is a bit strange, but it's probably just in there as a minimally adjusted copy and paste of the list structure entry. See my answer to Definition of tree structure in Lisp for a bit more about that.

这篇关于在LISP中更改列表的副本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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