请在2024年Clojure状态调查!分享您的想法。

欢迎!请参阅关于页面了解本网站的更多信息。

0 投票
Clojure

尝试定义一个名为“clear”的协议时似乎存在问题。

(defprotocol PClear

 (clear (link: o)))

=> PClear

(defrecord Foo (link: )

 PClear 
   (clear (link: o) o))

=> CompilerException java.lang.ClassFormatError: Duplicate method name&signature in class file xxxx/Foo, compiling:(NO_SOURCE_PATH:1:1)

我猜测这是由于与底层实现中Java方法Collection.clear()的名称冲突造成的。然而,这个错误在关于此问题的描述上非常不明确,而且从我能看到的情况来看,冲突的可能性似乎没有进行记录。

似乎有两个可能的解决方案来修复这个问题
a) 禁止使用"clear"作为协议方法名(在这种情况下,错误应该更具信息性,并且规则应该进行记录)
b) 在类文件格式中找到一种支持这个功能的方法(可能通过在JVM返回类型上重载,因为Collection.clear()返回void??)

6 个答案

0 投票

评论作者:bronsa

Mike,JVM不支持返回类型重载,所以你的第二个建议在技术上是不可能的。

阅读defrecord文档{quote}类将自动生成几个(clojure.lang)接口的实现:IObj(元数据支持)和
IPersistentMap,以及它们的所有超接口。
{quote}
{quote}

或许应该在这里提到java.util.Collection(甚至更好的,java.util.Map)。

0 投票

评论作者:alexmiller

我认为这是一个增强文档的请求。

0 投票

评论由:sohta发表

这可能超出了这个工单的范畴,但协议方法冲突可能会引起其他类型的错误

`
user=> (defprotocol P1 (finalize [this]))
P1
user=> (defrecord R1 [] P1 (finalize [this]))

编译器异常 java.lang.VerifyError: (类:user/R1, 方法:finalize 签名:()Ljava/lang/Object;) 在空栈上无法弹出操作数,编译中:...
user=> (defprotocol P2 (wait [this]))
P2
user=> (defrecord R2 [] P2 (wait [this]))
user.R2
user=> (def r (->R2))

'user/r

user=> (wait r)
编译器异常 java.lang.IllegalArgumentException: 未找到接口:user.P2中的单个方法:wait,用于协议:P2中的函数:wait,编译中:...
user=>
`

在我看来,如果defprotocol能以更详细的通知信息告警方法冲突那就更好了。

0 投票

评论由:mikera发表

@Nicola Mometto : 我相信JVM确实支持重载返回类型

"请注意,一个类中可能存在多个匹配的方法,因为尽管Java语言禁止一个类声明具有相同签名但不同返回类型的多重方法,但Java虚拟机并不禁止。虚拟机的这种灵活性可以用来实现各种语言功能。例如,协变返回可以通过桥接方法实现;桥接方法和正在被覆盖的方法将具有相同的签名,但不同的返回类型."

参见: http://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getMethod-java.lang.String-java.lang.Class...-

0 投票

评论作者:bronsa

对了对了,谢谢。

0 投票
...