3

Clojure 1.4でプリミティブ引数を使用してプロトコルを定義しようとしています(パフォーマンスに敏感なコードで不要なプリミティブボクシングを回避できるようにするため)。

(defprotocol A
  (foo [a ^long x]))

(extend-type java.lang.String A 
  (foo [s ^long x] (.charAt s x)))

これは問題なく動作するように見えますが、使用しようとすると例外が発生して失敗します。

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

私は何が間違っているのですか?

4

2 に答える 2

3

さらに調査した結果、プロトコルはまだプリミティブ型ヒントをサポートしていないようです (Clojure 1.4 の時点)。例を参照してください https://groups.google.com/d/topic/clojure-dev/HxBqIewc494/discussion

代替案は次のようです。

  • プリミティブ ヒントを使用して通常の関数を記述します。ポリモーフィズムを失います。
  • Java インターフェイスを使用する ( Clojure でインスタンスを構築するためにreifyを使用できます)
于 2012-08-28T05:59:16.497 に答える
2

から型ヒントを取り出し、その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

編集:

(extend-type java.lang.String A 
  (foo [s ^Long x] (type x)))
nil
core> (foo "abracadarbra" 3)
java.lang.Long
于 2012-08-28T04:28:59.037 に答える