2012-10-19 5 views
8

私は、一連の結果(Clojureベクトルに似ています)を表すJavaクラスを使用しています。私はしかし、私はがクラスを変更することはできません一般的なClojureのシーケンス機能(つまり、私は、それが配列の抽象化をサポートするかのようにクラスの振る舞いを持つようにしたい)と、このクラスを使用したいJavaクラスをClojureのシーケンスとして動作させる

はそれを作ることができませんclojure.lang.Seqableなどを実装してください。また、面倒くさい、クラスはjava.util.Collectionまたはjava.lang.Iterableを実装していません。

  • 使用iterator-seqオブジェクトの(既存の)イテレータ:

    は、私はいくつかのオプションを見ることができます。

  • ラップjava.util.Collection/clojure.lang.Sequable
  • を実装して、別のクラスのオブジェクトは、オブジェクトに

を照会することにより、Clojureのベクトルまたはシーケンスを構築する関数を作成し、他のオプションはありますか?最善のアプローチは何ですか?

+1

'iterator-seq'は内部的にオブジェクトのラップに関する2番目の点と同じことをします – Ankur

答えて

6

最も速く、最も簡単なのはiterator-seqです。

これは、コアClojureがseqによって呼び出されるSeqSourceのようなプロトコルを提供しないのはなぜですか?その後、非標準コレクションは、「InternalReduce」がreduceの仕組みと同様に、「seq」を供給するために「拡張」される可能性があります。

+7

seqは(a)コンパイラで使用されているため、Javaに優しい必要があります(b)非常に頻繁に呼び出されるため、可能な限り高速にする必要があります。プロトコルは多くのものよりも高速ですが、単純なインターフェイスのディスパッチほど高速ではありません。 – amalloy

+0

@amalloy次におそらく 'to-seq'関数 –

+0

"また、嫌なことに、クラスはjava.util.Collectionまたはjava.lang.Iterableを実装しません。 " – noahlz

2

を実装する私の最初のショットは、そのオブジェクトのレイジー配列を作成するには、次のようになります。

(defn sequify [obj] 
    (letfn [(inner [idx] 
       (when (< idx (.size obj)) 
          (cons (.get obj idx) 
           (lazy-seq 
            (inner (inc idx))))))] 
    (inner 0))) 

はちょうど適切な方法で.size.getを交換してください。

lazy-seqソリューションと比較してパフォーマンスを向上させたい場合は、ラッパーを作成する方が適切です。