分享您的想法,参与 2024 年 Clojure 状态调查!

欢迎!请参阅 关于 页面以获取更多有关该工作的信息。

+1
Java Interop

当前如果在 (bean) 生成的代理上运行 clojure.walk 函数,将引发异常

(clojure.walk/prewalk identity (bean (java.util.Date.)))

 (link: java) ERROR in (test-walk-bean) (:-1)
 (link: java) expected: (clojure.walk/prewalk identity b)
 (link: java)   actual: java.lang.UnsupportedOperationException: empty
 (link: java)  at clojure.core.proxy$clojure.lang.APersistentMap$ff19274a.empty (:-1)
 (link: java)     clojure.core$empty.invokeStatic (core.clj:5202)
 (link: java)     clojure.walk$walk.invokeStatic (walk.clj:49)
 (link: java)     clojure.walk$prewalk.invokeStatic (walk.clj:64)
 (link: java)     clojure.walk$prewalk.invoke (walk.clj:60)
 (link: java)     clojure.lang.AFn.applyToHelper (AFn.java:156)
 (link: java)     clojure.lang.AFn.applyTo (AFn.java:144)
 (link: java)     clojure.core$apply.invokeStatic (core.clj:657)

因为代理没有实现 empty,这是 clojure.walk 所必需的。此补丁添加了一个重现问题的测试和一个修复。

9 答案

0

评论者:alexmiller

请将重现步骤添加到描述中?

如果您尚未签署贡献者协议,请这样做,否则我们无法考虑该补丁。 https://clojure.org/community/contributing

谢谢!

0

评论者:sunng

看起来描述不可编辑。

我已经在补丁中包含了一个测试用例以重现此问题

(clojure.walk/postwalk identity (bean (java.util.Date.)))

我已经签署了协议,作为 (Ning Sun, [email protected], github:sunng87)

0

评论者:alexmiller

谢谢,我已经给你编辑权限

0

评论者:alexmiller

从这个角度稍微仔细看一下,我认为你提出的解决方案没有意义。"bean" 提供了 Java 对象的只读映射视图。"empty" 是一个修改操作,我们不支持具有类似目的的记录等。

我对问题陈述没有异议——我认为这是一个合理的用例。但我觉得修复应该在 "walk" 中,而不是在 "bean" 中。

0

评论者:sunng

更新描述并添加复现步骤

0

评论者:sunng

谢谢,Alex。我再次检查了 clojure.core/empty 的文档,它提到它委派给 IPersistentCollection 的 .empty,以返回同一类别的空集合。PersistentArrayMap 的实现只是返回一个缓存的空实例。它们都没有修改原始集合。所以我认为在这里返回一个空映射是合理的。

0

评论者:alexmiller

这些都是不可变集合,所以我谈论的不是实际的修改,而是从一个不可变结构到另一个不可变结构的变化。有几个现有的情况,我们有一些不可变集合不支持 empty,因为这从概念上说不通,比如具有相同目的的记录实例和映射条目。

我想说的是,我相信这是一种情况,无论特定的接口和 impl 路径是否允许调用该方法。在概念上,bean 创建的是一个 Java 对象的只读视图实例。清空对象视图是没有意义的——对象总是有字段(这与具有固定字段的记录相同,也与具有键/值的映射条目相同)。我相信 ClojureScript 中实际上有一个协议来标记集合是否可以清空,也许这在这里也很有意义。

0
参考:https://clojure.atlassian.net/browse/CLJ-2399 (由 sunng 报告)
0

我认为对 APersistentMap 增加特例,简单地在 walk 中使用 (into {} ... 可以解决这个问题。

...