Clojure 2024状态调查中分享您的想法!

欢迎!请参阅关于页面以获取更多关于这个网站如何工作的小信息。

+2
记录与类型
重新分类

我非常关注原子和compare-and-set作为并发原语,所以能够在deftype的可变字段上进行比较和设置而不产生额外的开销(更多的对象需要更多的内存和更多的指针要跟踪)真是太好了。

JVM有几种机制可以直接在字段上进行比较和设置(AtomicReferenceFieldUpdater、VarHandles等)。看起来deftype可以根据要求提供这样的功能。

目前使用AtomicReferenceFieldUpdater与deftype配合是可能的,但由于私有volatile字段和缺少静态初始化项,这变得有些繁琐。

1 答案

0

这个请求听起来很有趣,但更像是一个解决方案而不是问题。你能从那个角度重新表述它吗?

by
很抱歉,我就是不明白你想要什么。

我想这可能是第二次或第三次你对此给出类似的反馈(之前在 #clojure-dev 中),我已经重写一次,以(我认为)纳入那些反馈。感谢你抽出时间,但似乎很明显,我还是不明白。
by
就像,“我在尝试做 X,但我做不到。”X 是什么?需要在哪里做这个操作?
by
这是一场错误的喜剧,我之前基本上完全相反地误解了事情,并且移除了对我的特定问题的所有引用。

我编写了一个自定义的引用类型,实际上并不是 Clojure 的引用类型,而是一种类似的类型。一个含有盒内容的可控制变动的箱子。A 变得有点像原子类型的或 ref。

由于我的类型是一个引用类型,它有一个可变字段,指向引用本身指向的东西,以及其他字段,以便于其他操作。我想使用比较和设置来改变这个可变字段。

在纯 Clojure 中编写,这是通过在 deftype 字段中持有值的原子或 AtomicReference 包装器来完成的。这可行,但增加了 1 或 2 级指针追寻。我想去除这些额外的指针。

Java 为对可变字段直接进行比较和设置提供了至少两种不同的功能(它们可能要求字段为 volatile,我忘记了)。这两种机制都通过创建一种字段访问器对象来实现。典型的类模式似乎是创建字段访问器对象在静态初始化器中,然后在执行 cas 类型字段操作时使用它。

典型的模式不能与当前的deftype一起使用,因为虽然你可以使 deftype 字段可变,但这也使其私有,这使得构建字段访问对象变得困难。你无法从“外部”构建,因为该字段是私有的,并且 deftype 不提供静态初始化的方式。  有解决这个问题的方法,基本上是在你的 deftype 中添加一个什么也不做的函数,只创建并返回字段访问对象,然后在某个顶层静态上下文中构建一个你的 deftype 的空实例并调用该函数。这样是可行的,但感觉相当糟糕。

我最初尝试了创建一个空 deftype 实例,但最终只是编写了一个基本上是 deftype 的极致精简版,用于生成一个有字段和设置 AtomicReferenceFieldUpdater 的静态初始化器的类。这也奏效了,但依赖于对 asm 库的一些经验,以及一些注意事项以使其与 aot 编译良好配合(我认为这部分应该是正确的,但也不敢肯定)。

比较并设置是非常好的,如果能提供某种方法在 deftype 字段上执行比较和设置操作,而不需要我们想要比较和设置的操作的额外对象包裹。在 java/jvm 中有实现这些机制,但在 clojure 中利用它们很痛苦。
by
我认为 Alex 的请求尚未实现。有一个可变的对象,即使它使用原子引用和比较并设置(CAS),也是解决你所要解决问题的方法。使用可变状态和 CAS 解决什么问题?

如果我们能够触及到原始问题,那么可能有以下两种情况之一发生...要么 1) 我们会发现还有其他好的方法来解决 clojure 中存在的问题,要么 2) 我们有一个具有挑战性的未解决问题,这可能导致语言、库或新库的添加。
by
我来到这里是因为我觉得 mutable-state 可能是解决我面临的某个问题的好方法。我的 UI 基于 Clojure 代码,我需要实现/扩展 TableModel 之一并将其附加到 JTable 实例上。无论如何,我需要更新 TableModel 的内容... 我猜我可能需要完全重建它,每次都给 JTable 提供一个新的 TableModel,但这对于 Swing 来说似乎并不可行。我也可以使用 gen-class - 如果这是最好的方法,那会很好。我想显示的数据在我的应用状态中,应用状态在一个 atom 中。当数据发生变化时,我希望将更改发送到应用状态 atom 上的 swap!,并将这些更改传播回 TableModel,并通过 JTable 显示它们。所以问题是如何将 TableModel 连接到应用状态。
by
把所有这些写出来,我的解决方案似乎很明确... 直接从表模型中引用应用状态,并在应用状态发生变化时触发表格结构/行等更改。但是,我漏掉了一层。我实际上在使用 UI 的 FRP(函数响应式编程)。所以视图是应用状态的函数。视图函数是一个纯函数,但由于 Swing 中 JTable 的编写方式,它必须包含对实际数据的引用。因此,我可以为每次视图渲染创建一个新的表模型,使用某些自定义或现有的类在表模型中存储状态,违反这种 FRP 模型,或者我没有想到的其他方法。
...