Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List LISP非常简单的列表问题_List_Lisp - Fatal编程技术网

List LISP非常简单的列表问题

List LISP非常简单的列表问题,list,lisp,List,Lisp,我在学习lisp,我在这方面很新,所以我想知道 如果我这样做: (defparameter *list-1* (list 1 2)) (defparameter *list-2* (list 2 3)) (defparameter *list-3* (append *list-1* *list-2*)) 然后 (setf (first *list-2*) 1) *list-3* 我会得到(1 2 1 4) 我知道这是因为append将“保存资源”并为第一个块创建一个新列表,但实际上只会指向第

我在学习lisp,我在这方面很新,所以我想知道

如果我这样做:

(defparameter *list-1* (list 1 2))
(defparameter *list-2* (list 2 3))
(defparameter *list-3* (append *list-1* *list-2*))
然后

(setf (first *list-2*) 1)
*list-3*
我会得到(1 2 1 4)

我知道这是因为append将“保存资源”并为第一个块创建一个新列表,但实际上只会指向第二个块,因为如果我这样做:

(setf (first *list-1*) 0)
*list-3*
我将获得(1 2 1 4)个更符合逻辑(0 2 1 4)的安装


所以我的问题是,在lisp中还有什么其他情况是这样的,你们这些黑带Lisper如何知道如何处理这些不直观或不一致的东西?

append函数必须复制它的第一个参数,以避免修改现有的数据结构。因此,您现在有两个类似于
(1 2…
)的列表段,但它们是不同列表的一部分


一般来说,任何列表都可以是任何其他列表的尾部,但不能有一个列表对象作为多个列表的头部。

嗯,我们主要了解它是如何工作的,因此我们想象的不一致是有意义的

你需要做的是找到一些老式的方块图和指针图,我不能很容易地画出来,但是让我们来找出它

在第一个def参数之后,您得到了list-1,它是

(1 . 2 . nil)
点表示法;清单2是


你必须根据cons单元格来考虑列表。定义列表1和列表2时,如下所示:

(defparameter *list-1* (cons 1 (cons 2 nil)))
(defparameter *list-2* (cons 2 (cons 3 nil)))
然后,当您附加:

(defparameter *list-3* (cons 1 (cons 2 *list-2*)))
基本上,cons单元由两部分组成;一个值(汽车)和一个指针(cdr)。Append被定义为不更改第一个列表,以便复制该列表,但最后一个cdr(通常为nil)被更改为指向第二个列表,而不是第二个列表的副本。如果您愿意销毁第一个列表,则可以使用NCOC

试试这个:

(defparameter *list-3* (nconc *list-1* *list-2*))
然后观察
*list-1*
的值,它是(1 2 3),就像
*list-3*
一样


一般规则是,非破坏性函数(
append
)不会破坏现有数据,而破坏性函数(
ncoc
)会破坏现有数据。然而,未来破坏性功能的功能(
(setf cdr)
)不是第一个非破坏性功能的责任。

一种防御策略是避免共享结构

(defparameter *list-3* (append *list-1* *list-2* '()))

现在,新的
*list-3*
的结构是全新的,对
*list-3*
的修改不会影响
*list-2*
,反之亦然

所以我的问题是,在口齿不清的语言中,还有什么其他的情况是这样的,你们这些黑带口齿不清的人怎么知道如何处理这些不直观或不一致的东西

通过阅读精美手册?明确指出:

[…]复制除最后一个列表外的每个列表的列表结构。最后一个参数没有被复制;它成为前面列表串联的最后一个点对的cdr,或者如果前面没有非空列表,则直接返回

引述:

所以我的问题是,在口齿不清的语言中,还有什么其他的情况是这样的,你们这些黑带口齿不清的人怎么知道如何处理这些不直观或不一致的东西

我认为你在这里对一个比你想象的要大得多的主题有点苛刻。列表在Lisp中是一个相当复杂的概念,您需要了解这不是一个简单的数组。该标准提供了许多函数以各种方式操作列表。在这种情况下,您需要的是:

(concatenate 'list *list-1* *list-2*)
那么,为什么还有
append
?如果您可以省略复制最后一个列表,并且所有涉及的符号仍然返回正确的数据,那么这将大大提高计算时间和内存占用的性能<代码>附加在不使用副作用的函数式编程风格中特别有用


除了对cons电池、破坏性与非破坏性功能等的进一步解释,我将向您介绍一个很好的介绍:,作为完整的参考,请参阅第14章和第17章。

这不是点符号看起来的相似之处,而是(1.(2.nil))
(defparameter *list-3* (append *list-1* (copy-list *list-2*)))
(concatenate 'list *list-1* *list-2*)