2012-02-10 19 views
12

私はセサミライブラリを使用して、メモリ内トリプルストアでSPARQLクエリを実行しています。Javaイテレータのようなオブジェクトをクロージャシーケンスに変換するにはどうすればいいですか

私はこれを達成するためにClojureを使用しています。

クエリ結果はカスタムのIterator-like [1]オブジェクトです。このため、クロージャーseqはそのまま使用できません。

オブジェクトのようなカスタムJavaイテレータをclojureシーケンスに変換する最もエレガントな方法は何ですか?

私の頭に浮かんだもっとも明白で愚かなアイデアは、それをループしてクロージャーベクトルを構築することですが、この問題に対するより洗練されたアプローチがあると確信しています。実際Iteratorインタフェースを実装するオブジェクトにはイテレータのようなオブジェクトをラップする程度

[1] http://www.openrdf.org/doc/sesame2/api/info/aduna/iteration/Iteration.html

答えて

8

テストバージョン:

(defn iteration->seq [iteration] 
(seq 
    (reify java.lang.Iterable 
     (iterator [this] 
     (reify java.util.Iterator 
      (hasNext [this] (.hasNext iteration)) 
      (next [this] (.next iteration)) 
      (remove [this] (.remove iteration))))))) 
+2

これは、Iteratorの代わりにIterableをreifyするアプローチの1つです。もう一つはIteratorを正し、それを['iterator-seq'](http://clojuredocs.org/clojure_core/clojure.core/iterator-seq)でラップすることです。 – amalloy

+0

ニース、知っておいてよかった! – laczoka

5

どのように?以下のような何か(テストしていません):

(defn iteration-seq [iteration] 
    (iterator-seq 
    (reify java.util.Iterator 
    (hasNext [this] (.hasNext iteration)) 
    (next [this] (.next iteration)) 
    (remove [this] (.remove iteration))))) 

私の知る限り、標準Iteratorインタフェースを介しIterationインタフェースの唯一の利点は、(あなたがいること、それをコールする場合)、それが宣言することができますということですClojureで使用されていない例外をチェックします。

[更新:別の答えにコメントして@amalloyによって示唆されているように、iterator-seq代わりのseqを使用するために修正されたコード。]

+0

ありがとうございました。そうではありませんが、正しい方向に私を指摘し、* reify *の実用的な使い方を学ぶのを助けました。 – laczoka

+0

私はすでにテスト済みの正しいバージョンを取得していますが、評判の制限のために自己回答できません。 :) – laczoka

1

ピュア機能反復可能なツーカスタムイテレータのJava反復処理可能とイテレータ

(defn iter-seq 
    ([iterable] 
    (iter-seq iterable (.iterator iterable))) 
    ([iterable i] 
    (lazy-seq 
     (when (.hasNext i) 
     (cons (.next i) (iter-seq iterable i)))))) 

ための怠惰な系列符号は.iterator、.hasNextと.next呼び出しを置き換えます。

利点は、引数としてiterableをとるため、純粋に機能的です。他のポストされた解決策は反復可能な引数を取るので、関数は内部イテレータ状態に応じて異なるシーケンスを返す可能性があります。referential transparencyに違反します。 この機能は、その怠惰に関しても華やかです。

1

なぜclojure.core/iterator-seqを試してみませんか?

user=> (doc iterator-seq) 
------------------------- 
clojure.core/iterator-seq 
([iter]) 
    Returns a seq on a java.util.Iterator. Note that most collections 
    providing iterators implement Iterable and thus support seq directly. 

あなたは上記のドキュメンテーション文字列で見ることができるように、あなたも明示的iterator-seqを使用する必要はないかもしれません。 REPLのシーケンスとしてJavaイテレータを扱うだけでしたか?

+0

iterator-seqは明示的にjava.util.Iteratorでのみ動作しますが、ここで説明するオブジェクトはinfo.aduna.iteration.Iterationであるため、これは動作しません。 iterator-seqを使用すると、ClassCastExceptionが発生します。 – PaulaG

関連する問題