列表如何以 Common Lisp 中的数组不可能的方式共享结构?

How can lists share structure in ways that are impossible for arrays in Common Lisp?

我正在尝试通过 Common Lisp:对符号计算的简单介绍 来学习 Common Lisp。在第 13 章(倒数第二章)中,本书介绍了数组。

因此,作者对列表和数组进行了对比。他说:

Because storage in arrays is contiguous, we can access each element of an array as fast as any other element. With lists, we have to follow a chain of pointers to get from one cons cell to the next, so depending on the length of the list, it can take much, much longer to access the last element than the first. Efficient access is the prime advantage arrays have over lists. Another advantage is that in most implementations, an array uses only half as much memory as a list of equal length. But lists also have some advantages over arrays. Lists of arbitrary length are easily built up element by element, either recursively or iteratively. It is not as easy to grow an array one element at a time. Another advantage of lists is that they can share structure in ways that are impossible for arrays, but we won’t get into the details of that in this book.

我理解所有评论,但最后一个故意含糊不清:

Another advantage of lists is that they can share structure in ways that are impossible for arrays, but we won’t get into the details of that in this book.

在列表的数据结构中可能但在数组中不可能的结构份额究竟是什么?

谁能给我举个例子来说明这一点?

谢谢。

例如,创建两个共享尾部的列表:

(defparameter *l1* (list 1 2 3))
(defparameter *l2* (cons 0 (cdr *l1*))) ; (0 2 3)

现在,(eq (cdr *l1*) (cdr *l2*))t,修改一个列表可以修改另一个:

(setf (second *l1*) 10)
; now *l1* is (1 10 3)
; and *l2* is (0 10 3)

注意数组 can 也共享结构:

(defparameter *a1* (make-array 10 :initial-contents (loop for i from 1 to 10 collect i)))
; now *A1* is #(1 2 3 4 5 6 7 8 9 10)
(defparameter *a2* (make-array '(2 3) :displaced-to *a1* :displaced-index-offset 3))
; now *A2* refers to a part of *A1*: #2A((4 5 6) (7 8 9))

现在,修改 *a1* 也会修改 *a2*:

(setf (aref *a1* 6) 123)
; now *a1* is #(1 2 3 4 5 6 123 8 9 10)
; and *a2* is  #2A((4 5 6) (123 8 9))

列表和数组之间的区别在于 way 结构是共享的:列表可以共享 tails 而数组可以共享 连续内存段.