真是一场错误的喜剧,我之前基本上反着理解了这些事情,并移除了所有与我特定问题相关的引用。
我写了一个定制的引用类型,这不是clojure的引用类型,但是一种类似的东西。一个具有控制变动的盒状结构,用于存储盒子的内容。A最终变得有点像是原子或ref一样。
由于我的类型是引用类型,它有一个可变字段,指向引用本身所指向的内容,以及其他用于其他操作的字段。我想使用比较和设置的方法修改这个可变字段。
在“纯”clojure中,唯一通过使用一个atom或AtomicReference包装器在deftype字段中存储的值来实现此操作的途径。这可行,但添加了1或2级指针追踪。我希望去除这些额外的指针。
Java提供了至少两种直接在可变字段上执行比较和设置的不同设施(它们可能要求字段必须是volatile的,我忘了)。这两个机制都通过创建一种字段访问器对象来实现。对于类的一个典型模式似乎是创建字段访问器对象在静态初始化器中,然后在需要做cas类型操作的字段实例时使用它。
典型的模式在deftype中无法使用,因为尽管你可以将deftype字段设置为可变的,但这也使其变为私有,这会使得创建字段访问器对象变得困难。你不能从“外部”创建它,因为字段是私有的,且deftype不提供静态初始化的方式。基本上有办法解决这个,就是在你的deftype中添加一个什么也不做的函数,但只是为了创建和返回一个字段访问器对象,然后在某个顶层的静态上下文中创建一个假实例并调用该函数。所以,这本来是可以实现的,但非常糟糕。
我最初是尝试了模拟deftype实例的方法,但最终只是编写了一个极其简化的deftype版本,用于生成具有字段和静态初始化器的类,该初始化器为特定字段设置AtomicReferenceFieldUpdater。这同样有效,但需要一些asm库的经验,并且要小心使其能够在aot编译中良好工作(我认为我已经正确处理了这个部分,但不敢肯定)。
比较和设置非常棒,如果能提供一种方式在不需要额外对象包装的情况下对deftype字段进行比较和设置,那就更好了。在java/jvm中存在实现这种机制的机制,但在Clojure中很难利用。