在 Clojure 中访问可变的 java.util.List

Access mutable java.util.List in Clojure

提问人:tRi11 提问时间:9/16/2020 更新时间:9/16/2020 访问量:385

问:

我正在使用第三方 Java 库,其中一个库事件将 java.util.List 作为参数传递,Clojure 将其公开为 clojure.lang.APersistentVector。我遇到的问题是库要求我改变该列表以实现我所追求的功能。但是,由于 Clojure 已将列表返回为 APersistentVector,因此所有可变方法都会引发 UnsupportedOperationException。

是否可以强制 Clojure 使用可变的 List Java 实现而不是不可变的 Clojure 版本?

我很欣赏这非常不像 Clojure,但这是库的工作方式,现在,我只想让事情正常工作。

谢谢

保罗

爪哇岛 列表 Clojure(克洛朱尔酒店) 可变

评论


答:

0赞 andy_fingerhut 9/16/2020 #1

当您说“哪个 Clojure 公开为 clojure.lang.APersistentVector”时,您的意思尚不清楚。如果 Clojure 调用一个 Java 方法,该方法返回一个带有 java.util.ArrayList 类的对象 x,则在 Clojure 中调用应显示 java.util.ArrayList。(class x)

您正在使用的库中是否发生了一些转换代码,也许是 Java 方法调用的 Clojure 包装器,正在执行此转换?

Clojure REPL 会话示例显示您确实可以获取 java.util.ArrayList 对象并在 Clojure 代码中对其进行更改:

user=> (def mutlist1 (java.util.ArrayList. [1 2 3]))
#'user/mutlist1
user=> mutlist1
[1 2 3]
user=> (class mutlist1)
java.util.ArrayList
;; add a new element -1 at index 1
user=> (.add mutlist1 1 -1)
nil
user=> mutlist1
[1 -1 2 3]

评论

0赞 tRi11 9/16/2020
谢谢,我正在尝试实现的是一个类似于这样的功能:github.com/ngs-doo/TemplaterExamples/blob/......我使用reify来扩展接口,该事件与java.util.List挂钩(如果我使用ArrayList,则不会调用它)。但是,提供的列表类是 clojure.lang.PersistentVector。我试过类型提示,这没什么区别,
0赞 andy_fingerhut 9/16/2020
您是否在某个时候使用 Clojure 向量调用 API,然后 Java 库将其传回给您进行修改?因为 Clojure 持久序列数据结构确实实现了 java.util.List 接口(但不是突变方法,根据该接口的 Java API 文档,这些方法是可选的)。
0赞 tRi11 9/16/2020
是的,它通过将 java.util.List 连接到接口实现 (github.com/ngs-doo/TemplaterExamples/blob/...) 来配置。然后,它在 Clojure 数据结构中传递并执行,但是当调用函数时,传递的列表是持久的,并且在尝试更改它时会出错。
0赞 andy_fingerhut 9/16/2020
也许我在这里想得太简单了,但是如果你的 Clojure 代码调用你使用 reify 创建的这个对象,并且你的 Clojure 代码正在向它传递一个 Clojure 向量,那么这当然是不可变的。您应该更改调用该方法的代码,以向其传递 java.util.List 接口的可变实现,例如 java.util.ArrayList。如果你有一个 Clojure 向量 v,你可以通过调用 (java.util.ArrayList. v) 来创建这样的 ArrayList。如果这不是正在发生的事情,那么我不明白是谁在调用您的 reify 对象的方法并向其传递 Clojure 向量
0赞 tRi11 9/16/2020
谢谢,问题是我对 Java 互操作缺乏了解。