LISP非常简单的列表问题

时间:2009-01-09 03:34:41

标签: 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)

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

(setf (first *list-1*) 0)
*list-3*

我将得到(1 2 1 4)更符合逻辑的(0 2 1 4)

的instade

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

6 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:4)

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

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

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

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

答案 2 :(得分:3)

您必须根据缺点单元格来考虑列表。定义列表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)。附加被定义为不更改第一个列表,因此复制,但最后一个cdr(通常为nil)更改为指向第二个列表,而不是第二个列表的副本。如果你愿意销毁第一个列表,你可以使用nconc。

试试这个:

(defparameter *list-3* (nconc *list-1* *list-2*))

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

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

答案 3 :(得分:3)

引用:

  

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

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

(concatenate 'list *list-1* *list-2*)

那么,为什么还有append?好吧,如果您可以省略复制最后一个列表,并且所涉及的所有符号仍然返回正确的数据,这可以显着提高计算时间和内存占用量。 append在不使用副作用的函数式编程风格中特别有用。

除了关于利弊细胞,破坏性与非破坏性功能等的进一步解释之外,我将向您介绍一个很好的介绍:Practical Common Lisp, Ch. 12,并且为了完整的参考,Common Lisp Hyperspec,看看在第14章和第17章。

答案 4 :(得分:0)

  

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

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

  

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

答案 5 :(得分:-2)

嗯,主要是我们学习它是如何工作的,所以我们想象的不一致是有意义的。

你需要做的是找到一些我不能轻易画出来的老式块和指针图,但让我们弄明白。

在第一个defparameter之后,你有 list-1 ,这是

(1 . 2 . nil)

用点符号表示; list-2

(2 . 3 . nil)