2024年Clojure调查!中分享您的想法。

欢迎!请参阅关于页面以了解更多有关此功能的信息。

+1
协议

可以将协议扩展到原始数组,但如果指定类型类,则有一点复杂

(defprotocol P (p [_])) (extend-protocol P (Class/forName "[B") (p [_] "bytes")) (p (byte-array 0)) ;; => "bytes"

但是,如果您尝试执行多项此类操作,则会导致错误

`
(extend-protocol P
(Class/forName "[B") (p [_] "bytes")
(Class/forName "[I") (p [_] "ints"))
编译器异常java.lang.UnsupportedOperationException:nth不支持此类:Character,编译:(NO_SOURCE_PATH:1:1)

clojure.lang.Compiler.analyze (Compiler.java:6380)
clojure.lang.Compiler.analyze (Compiler.java:6322)
clojure.lang.Compiler$MapExpr.parse (Compiler.java:2879)
clojure.lang.Compiler.analyze (Compiler.java:6369)
clojure.lang.Compiler.analyze (Compiler.java:6322)
clojure.lang.Compiler$InvokeExpr.parse (Compiler.java:3624)
clojure.lang.Compiler.analyzeSeq (Compiler.java:6562)
clojure.lang.Compiler.analyze (Compiler.java:6361)
clojure.lang.Compiler.analyze (Compiler.java:6322)
clojure.lang.Compiler$BodyExpr$Parser.parse (Compiler.java:5708)
clojure.lang.Compiler$FnMethod.parse (Compiler.java:5139)
clojure.lang.Compiler$FnExpr.parse (Compiler.java:3751)

原因
UnsupportedOperationException nth不支持此类:Character

clojure.lang.RT.nthFrom (RT.java:857)
clojure.lang.RT.nth (RT.java:807)
clojure.core/emit-hinted-impl/hint--5951/fn--5953 (core_deftype.clj:758)
clojure.core/map/fn--4207 (core.clj:2487)
clojure.lang.LazySeq.sval (LazySeq.java:42)
clojure.lang.LazySeq.seq (LazySeq.java:60)
clojure.lang.RT.seq (RT.java:484)
clojure.lang.RT.countFrom (RT.java:537)
clojure.lang.RT.count (RT.java:530)
clojure.lang.Cons.count (Cons.java:49)
clojure.lang.Compiler.analyze (Compiler.java:6352)
clojure.lang.Compiler.analyze (Compiler.java:6322)

`

在{parse-impls}中的代码将第二个{(Class/forName "[I")})视为函数,而不是新的类型。一个解决方案是同时只扩展协议到一个类型。

如果在这里有一种语法可以指定原始数组类型,那就更好了(正在进入增强区域)- 我们已经有{bytes,ints,longs}等语法用于类型提示,对我来说这些看起来很完美。

5 答案

0

评论者:nahuel

在扩展单个数组类型时也会出错

`
(extend-protocol P
字符串(p [_] "string")
(Class/forName "[B") (p [_] " ints"))
)

; =>编译器异常java.lang.UnsupportedOperationException:nth不支持此类...
`

但更改声明顺序可以解决这个问题

`
(extend-protocol P
(Class/forName "[B") (p [_] " ints"))
字符串(p [_] "string")
)

; => OK
`

0

评论者:alexmiller

重复CLJ-1790

0

评论者:alexmiller

经过进一步检查,我认为这不是CLJ-1790的重复问题,而是一个相关的问题。

0

评论者: gchapman

使用Class/forName有一个更进一步的麻烦,因为已在{{this}}参数类型提示上不再发射

user=> (extend-protocol P (Class/forName "[B") (p [this] (aget this 0))) 反射警告,NO_SOURCE_PATH:2:50 - 在clojure.lang.RT上调用的静态方法aget无法解析(参数类型:未知,int)。

对于非原始数组也会生成反射警告(所以仅仅支持{{ints}}等并不能完全解决这个问题)。提供一个涵盖所有向数组扩展协议的问题的解决方案会更好。

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