在问题文本中给出的示例中,根本没有发生结构共享。这是因为向量被实现为树,其中实际元素存储在大小为 32 的叶节点中(最终叶单独存储为向量的“尾部”——性能优化),分支节点同样是 32 路的. 因此,为了使结构共享发挥作用,需要一个足够大的向量:
;; a base vector:
(def v1 (vec (range 31)))
;; no structural sharing -- all elements are copied:
(def v2 (conj v1 31))
;; leftmost leaf of internal tree uses v2's tail as its internal array:
(def v3 (conj v2 32))
;; leftmost leaf shared with v3
(def v4 (conj v3 33))
通常,每当conj
将对象添加到现有向量上时,新向量要么 (1) 与原始向量共享整个内部树,但有一个新的尾部,或者 (2) 在原始向量内部树的每个级别上与原始向量共享, 除了最右边的节点之外的所有节点(并且可能有一个比原始节点高一级的内部树)。(显然所有元素都与新向量共享。)
至于按索引查找值,在每种情况下都以相同的方式发生——向量不关心它们的结构是否恰好与其他向量共享(并且没有理由需要它们,因为它永远不会改变)。