Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
clojure中持久数据结构的内存共享_Clojure - Fatal编程技术网

clojure中持久数据结构的内存共享

clojure中持久数据结构的内存共享,clojure,Clojure,我已经开始学习Clojure,正在阅读关于结构共享的文章。我对以下情况感到困惑: 以下clojure代码按以下定义的顺序在REPL中键入: 1) (定义a[1 2 3]), 2) (def b a), 3) (defa(conj a4)), 4) (def b(conj b 5)), 在第4步之后,a和b是否共享前三个元素的结构,或者在执行第4步时复制所有值?如果结构是共享的,Clojure将如何返回索引3处的值 这有点关系,但我仍然感到困惑。任何形式的帮助都将不胜感激。在问题文本中给出的示例中

我已经开始学习Clojure,正在阅读关于结构共享的文章。我对以下情况感到困惑: 以下clojure代码按以下定义的顺序在REPL中键入:

1)
(定义a[1 2 3])

2)
(def b a)

3)
(defa(conj a4))

4)
(def b(conj b 5))

在第4步之后,a和b是否共享前三个元素的结构,或者在执行第4步时复制所有值?如果结构是共享的,Clojure将如何返回索引3处的值


这有点关系,但我仍然感到困惑。任何形式的帮助都将不胜感激。

在问题文本中给出的示例中,根本不会发生结构共享。这是因为向量被实现为树,其中实际元素存储在大小为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))
通常,每当一个
将一个对象连接到一个现有向量上时,新向量要么(1)与原始向量共享整个内部树,但有一个新的尾部,要么(2)与原始向量共享原始向量内部树的每一级,除最右边的节点外的所有节点(并且可能有一个比原始向量高一级的内部树)。(很明显,原始向量的所有元素都与新向量共享。)


至于通过索引查找值,在每种情况下都是以相同的方式进行的——向量不关心它们的结构是否与其他向量共享(并且没有理由需要,因为它从不改变).

回答得很好。我希望有一个页面,上面有图像中解释的每个基本clojure数据结构。列表很明显,但向量并不是那么多,而且命名起来像c++/java向量,而实际上基于树的结构只会增加关于它们是否持久的混淆。我不确定是否没有共享任何内容。你是假设即使在第二步之后,a和b也不会共享任何数据?而且,如果在第四步之后,如果他们不共享数据,那么conj几乎是O(n)操作,这是昂贵的。@abhishekmahawar在结构(相对于元素),
a
b
确实不会共享任何数据。这并不意味着
conj
O(n),因为对可执行的复制量有限制(每个树级别一个包含32个对象的数组)。碰巧这种操作模式对缓存非常友好,而今天的CPU缓存大小使用小于32的数组根本不会为您节省太多时间。支持这一主张的经验证据来自基准测试的形式,在基准测试中,向量显示出优异的性能。@abhishekmahawar有一个很好的索引图(查找)Bagwell&Rompf's;8中具有各种分支因子的向量的更新时间似乎是更新的最佳点(8而不是2,这意味着在示例中复制而不是共享基本上是一种优化!),而32的更新速度稍慢,但索引速度较快。在不同的机器上,结果可能会稍有不同,但图形的总体形状会相同。@abhishekmahawar,等等,我想我误读了你的评论。在第二步之后,
a
b
只是引用同一个向量。这不是结构性的然而,共享是关于在不同的向量之间共享内部树的一部分;它只是给两个Clojure变量赋予相同的值的一种情况。(您可以类似地说
(def a(java.util.HashMap.))
,放入一些内部元素,然后说
(def b a)
。此时
a
b
将引用相同的
HashMap
,但这不是结构共享的情况;事实上,这个概念根本不适用于
java.util.HashMap
s。)