【问题标题】:Extend Clojure protocol to a primitive array将 Clojure 协议扩展为原始数组
【发布时间】:2012-12-18 01:08:38
【问题描述】:

我想扩展一个 Clojure 协议来处理 Java 原始数组。

(defprotocol PVectorisable
  (to-vector [a]))

(extend-protocol PVectorisable
  ??????
    (to-vector [coll]
      (Vectorz/create ^doubles coll))
  java.util.List
    ... other implementations......)

这是否可能,如果可以,上面的扩展协议定义中需要添加什么(代替“??????”)?

【问题讨论】:

    标签: arrays clojure protocols primitive-types


    【解决方案1】:

    最简单的解决方案可能是通过反射以编程方式获取类。

    (defprotocol do-a-thing
     (print-thing [thing]))
    
    (extend-protocol do-a-thing
     (class (float-array 0))
      (print-thing [_]
       (println "it's a float array")))
    

    Java 的数组有一些奇怪的名字。例如,浮点数组是[F。如果你尝试直接在 REPL 中使用它,它会被无与伦比的[ 阻塞。但是,您仍然可以将此名称与 Class/forName 一起使用。

    (defprotocol do-another-thing
     (print-another-thing [thing]))
    
    (extend-protocol do-another-thing
     (Class/forName "[F")
      (print-another-thing [_]
       (println "it's still a float array")))
    

    This article 详细介绍了数组类。

    【讨论】:

    • 谢谢!这有点难看,但 Class/forName 解决方案似乎工作得很好。
    • 我发现这只适用于扩展协议定义中的第一个类。如果不支持,Clojure 1.5.1 会给出 java.lang.UnsupportedOperationException 并抱怨 Character 或 Symbol 类型不支持 nth。
    【解决方案2】:

    正如 hadronzoo 所指出的,Class/forName 解决方案仅在它是 defprotocol 的第一个定义时才有效,这将解决方案限制为每个协议只有一个数组类型(或必须进行多个 defprotocol 定义)。这可以通过宏来处理多种数组类型,以避免读取器无法解析数组符号的问题:

    (defprotocol ISample
      (sample [_]))
    
    (defmacro extend-protocol-arrays []
      (let [ba (symbol "[B")
            ia (symbol "[I")
            oa (symbol "[Ljava.lang.Object;")]
      `(extend-protocol ISample
         ~ba
         (sample [this#] (println "Byte Array"))
         ~ia
         (sample [this#] (println "Int Array"))
         ~oa
         (sample [this#] (println "Object Array")))))
    
    (extend-protocol-arrays)
    
    (sample (byte-array 0))
    
    (sample (int-array 0))
    
    (sample (make-array Object 0))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-21
      • 2017-06-03
      • 2012-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多