Clojure 使用带有原始参数的协议

Clojure 使用带有原始参数的协议,clojure,protocols,primitive,Clojure,Protocols,Primitive,我正试图在Clojure 1.4中使用原语参数定义一个协议(这样我就可以避免在性能敏感代码中不必要的原语装箱): 这看起来工作正常,但在我尝试使用它时出现异常: (foo "abracadarbra" 3) => ClassCastException XXXX cannot be cast to clojure.lang.IFn$OLO 我做错了什么?从defprotocol中取出类型提示,并将其保留在extend type (defprotocol A (foo [a x])) (e

我正试图在Clojure 1.4中使用原语参数定义一个协议(这样我就可以避免在性能敏感代码中不必要的原语装箱):

这看起来工作正常,但在我尝试使用它时出现异常:

(foo "abracadarbra" 3)
=> ClassCastException XXXX cannot be cast to clojure.lang.IFn$OLO

我做错了什么?

defprotocol
中取出类型提示,并将其保留在
extend type

(defprotocol A
(foo [a x]))

(extend-type java.lang.String A 
  (foo [s ^Long x] (.charAt s x)))
nil
core> (foo "abracadarbra" 3)
\a
或者您可以更改类型提示,如下所示:

(defprotocol A
(foo [a ^Long/TYPE x]))

(extend-type java.lang.String A 
  (foo [s ^long x] (.charAt s x)))
nil
core> (foo "abracadarbra" 3)
\a
如果没有
defprotocol

编辑:


在进一步研究之后,协议似乎还不支持原语类型提示(从Clojure 1.4开始)。见例

替代方案似乎是:

  • 编写带有基本提示的常规函数。你失去了多态性
  • 使用Java接口(可用于在Clojure中构建实例)

谢谢你,亚瑟!这是可行的-但它实际上是在使用函数的原始版本吗?嗯,我当时并没有完全解决这个问题,因为我的意图是找到一种避免原始参数装箱的方法…我可能读错了,很难说,因为(类型4)报告了相同的。。。
(defprotocol A
(foo [a ^Long/TYPE x]))

(extend-type java.lang.String A 
  (foo [s ^long x] (.charAt s x)))
nil
core> (foo "abracadarbra" 3)
\a
(extend-type java.lang.String A 
  (foo [s ^Long x] (type x)))
nil
core> (foo "abracadarbra" 3)
java.lang.Long