Clojure:“持久!”会发生什么?在TransientVector上被调用?

时间:2018-11-06 18:28:30

标签: java data-structures clojure

我正在浏览clojure编译器的源代码,并且遇到了似乎与源代码不匹配的行为。

PersistentVectorhttps://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/PersistentVector.java)中的clojure.lang类(按位分区的特里实现)具有以下字段:

  1. cnt(int)
  2. 尾巴(Object [])
  3. 根(节点)
  4. shift(int)
  5. _meta

Node有两个字段。 editarray

array存储子项(trie的分支),而editAtomicReference<Thread>edit包含null的{​​{1}}和PersistentVector的创建线程的ID。 This博客文章很好地解释了瞬态实际上是如何工作的。与我的查询有关的关键点是:

  1. 由暂态创建的任何新节点将TransientVector字段设置为暂态根的字段,其中包含创建线程的ID
  2. edit上调用persistent!时,根节点的TransientVector设置为null,并从该根节点创建一个edit,并将其返回。可以在源代码中here看到这种行为。

请注意,仅根节点的PersistentVector字段设置为null,因此,由暂态创建的edit设置为线程ID的任何新节点都不会受到影响。因此,我编写了以下代码来测试这种情况:

edit

此代码的输出是:

package clojure.lang;

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList<Integer> arr = new ArrayList<>();
        for (int i=0; i<32; i++) {
            arr.add(i);
        }

        PersistentVector pv1 = PersistentVector.create((Iterable)arr);
        PersistentVector.TransientVector tv1 = pv1.asTransient();

        tv1.conj(-1);
        PersistentVector.Node n = (PersistentVector.Node) tv1.root.array[0];
        System.out.println(n.edit);

        PersistentVector pv2 = tv1.persistent();
        n = (PersistentVector.Node) pv2.root.array[0];
        System.out.println(n.edit);

        System.out.println("end");

    }
}

这就是这段代码的作用:

  1. 创建一个包含32个元素的Thread[main,5,main] null end 。该向量将具有完整的尾部,因此向其添加任何元素将导致创建新节点

  2. 从中创建了一个PersistentVector

  3. 为瞬变添加一个元素。这将导致创建一个新节点,并将其存储为TransientVector的子节点。

  4. 打印此新节点的root字段的值

  5. 使瞬态edit

  6. 打印同一节点的persistent字段。

该字段的值将重置为null!我不知道怎么回事。我曾尝试在intellij中设置字段监视点,但是调用edit时根本不会触发该断点。这种行为背后的原因是什么?我已经尝试过使用具有更多元素的向量,并且在tv1.persistent()上调用edit时,所有子节点的persistent字段的值都会重置。

0 个答案:

没有答案