我不清楚 Clojure 中的结构共享。下面是一个函数 xconj 取自《Joy of Clojure》(顺便说一句,很棒的书)。
;;Building a naive binary search tree using recursion
(defn xconj [t v]
(cond
(nil? t) {:val v :L nil :R nil}
(< v (:val t)) {:val (:val t) :L (xconj (:L t) v) :R (:R t)}
:else {:val (:val t) :L (:L t) :R (xconj (:R t) v)}))
如果定义两棵树 t1 和 t2 如下所示。
(def t1 (xconj (xconj (xconj nil 5) 3) 2))
(def t2 (xconj t1 7))
很明显,左子树由 t1 和 t2 共享
user> (identical? (:L t1) (:L t2))
true
但是,如果要创建一棵新树 t3,则通过在 t1 的左子树中插入新值“1”,如下所示:
(def t3 (xconj t1 1))
这是否会产生一棵全新的树,其中所有值都被复制且没有结构共享,或者某些结构仍会被共享?如果左分支更大,比如 2->3->4->5->6->7(*root) 并且 1 被插入到左子树中,那么某些结构共享会持续存在吗?
到要插入新值的位置的路径上的节点将被替换,但至少有两件事应该注意才能了解整个故事:
更换非nil
过程中的节点xconj
操作保留其子树之一及其值;只有一棵子树被换出。 (如果沿着“左,左,左”路径替换节点,那么位于“左,左,右”位置的节点将被共享。)因此,即使沿路径的所有节点,许多结构也可能被共享。其中一片叶子的路径被替换。
-
被替换的节点是地图。如果它们大于三个键,那么使用assoc
/ assoc-in
/ update-in
而不是构建新地图:
...
(< v (:val t)) (update-in t [:L] xconj v)
...
新节点图将能够与旧节点图共享结构。 (再次强调,这里没有意义,因为节点太小;但在不同的上下文中,这可能会产生巨大的差异。)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)