简答
树结构定义中的最后一句话提出了一个
问题,也就是说,cdrs 也可以这样说吗?
我认为答案是“是的”。 列表结构 有一个类似的定义,其措辞几乎相同。在列表结构中,关于 cons 的 car 的值是否是列表结构的一部分,存在更多混淆的可能性,因为可能会出现问题,例如,“在列表中替换 X 意味着什么(X (X)是)?” cdr 并没有太大的问题,因为 cdr 是列表的 rest ;它显然是列表结构的一部分。
对于树形结构,我认为歧义较少;汽车或 cdr 中的缺点是子树。 树结构和列表结构的定义在某些地方几乎相同,如果有人写了列表结构的定义,我不会感到惊讶,然后将其复制为 树形结构,从而实现准确所需的最少更改。即使它所回答的问题在实践中可能不会出现,这也会留下一些关于汽车的信息。
更长的答案
我们看看列表结构的定义,对比一下:
list structuren。 (列表的)组成列表的一组cons。
请注意,虽然每个此类缺点的汽车组件都是
列表结构,作为列表元素的对象(即
列表中每个缺点的汽车的对象)不是
它们本身是其列表结构的一部分,即使它们是 cons,除了
在(循环)情况下,列表实际上包含其中一个
尾巴作为一个元素。 (列表的列表结构有时是
按顺序冗余地称为其“顶级列表结构”
强调作为列表元素的任何 conses 不是
参与。)
注意这些不同的具体地方:
(列表结构)请注意,虽然每个此类 cons 的 car 组件都是
列表结构,作为列表元素的对象(即
列表中每个缺点的汽车的对象)不是
它们本身是其列表结构的一部分,即使它们是 conses。
(树结构)请注意,虽然每个此类 cons 的 car 组件都是
树结构,对象是树中每个缺点的汽车
本身不是其树结构的一部分,除非它们也是
缺点。
这意味着在
(1 (2) 3) == (cons 1 (cons (cons 2 nil) (cons 3 nil)))
列表结构中有三个个cons单元,树结构中有四个个cons单元。
这实际上在哪里重要?准确定义这些术语变得很重要,这样规范才能轻松定义特定函数遍历或修改列表或树的哪些部分。
nsubst 可以修改树形结构
例如,函数nsubst and friends,其文档指出:
nsubst、nsubst-if 和 nsubst-if-not 可能会改变 tree structure 的
树。
树结构的具体定义让我们了解nsubst可能改变和不可能改变的事物。
tree structuren。 (一棵树)组成树的一组cons。
请注意,虽然每个此类缺点的汽车组件都是
树结构,对象是树中每个缺点的汽车
本身不是其树结构的一部分,除非它们也是
缺点。
所以,这告诉我们的是,对于树中的任何 cons 单元 x,nsubst 可能会执行 (setf (car x) ...),因此 (car x) 稍后可能会有所不同,但它不会修改 (car x) 将返回的实际对象(当然,除非这是一个缺点)。这在 (car x) 的值是一个内部可能有树的对象的情况下可能很重要。例如,nsubst 不会下降到向量,但会替换向量:
(let* ((l (list 1 2 3)) ; a list
(v (vector 0 l 4)) ; a vector that contains the list (and other elements)
(tree (cons l v))) ; a tree containing the list and the vector
(nsubst 'x l tree)) ; replace the list in the tree with X
;=> (X . #(0 (1 2 3) 4)) ; nsubst doesn't descend into the vector, because it's
; not tree structure
delete-duplicates 可以修改列表结构
另一方面,delete-duplicates 只会修改列表结构:
delete-duplicates,当序列是一个列表时,允许设置任何
该序列中顶级列表结构的一部分 car 或 cdr。
当序列是一个向量时,delete-duplicates 被允许改变
矢量的尺寸并将其元素滑入新的
位置而不用置换它们来产生结果向量。