Clojure中的结构共享

Clojure中的结构共享,clojure,Clojure,我不清楚Clojure的结构共享。下面是一个函数xconj,取自Clojure的喜悦(顺便说一句,这本好书) 很明显,左子树由t1和t2共享 user> (identical? (:L t1) (:L t2)) true 但如果要创建一个新树t3,则在t1的左子树中插入一个新值“1”,如下所示: (def t3 (xconj t1 1)) 这会导致一个全新的树,其中所有值都被复制,没有结构共享,还是某些结构仍然被共享?如果左分支更大,比如说2->3->4->5->6->7(*根),并且

我不清楚Clojure的结构共享。下面是一个函数xconj,取自Clojure的喜悦(顺便说一句,这本好书)

很明显,左子树由t1和t2共享

user> (identical? (:L t1) (:L t2))
true
但如果要创建一个新树t3,则在t1的左子树中插入一个新值“1”,如下所示:

(def t3 (xconj t1 1))

这会导致一个全新的树,其中所有值都被复制,没有结构共享,还是某些结构仍然被共享?如果左分支更大,比如说2->3->4->5->6->7(*根),并且在左子树中插入了1,那么结构的共享会持续吗?

将替换指向插入新值位置的路径上的节点,但至少有两件事需要注意才能了解整个情况:

  • xconj
    操作过程中替换非
    nil
    节点将保留其一个子树及其值;只交换了一个子树。(如果沿路径“left,left,left”替换节点,则位置“left,left,right”处的节点将被共享。)因此,即使沿路径到其中一个叶的所有节点都被替换,许多结构也可能被共享

  • 被替换的节点是映射。如果它们大于三个键,则使用
    assoc
    /
    assoc in
    /
    updatein
    而不是构建新地图是有意义的:

    ...
    (< v (:val t)) (update-in t [:L] xconj v)
    ...
    
    。。。
    (
    新节点映射将能够与旧节点映射共享结构。(再一次,由于节点太小,在这里没有意义;但在不同的上下文中,这可能会产生巨大的差异。)


  • 感谢/assoc-in中的更新建议,这绝对是更新地图的更简洁的方式。
    (def t3 (xconj t1 1))
    
    ...
    (< v (:val t)) (update-in t [:L] xconj v)
    ...