2012-07-10 7 views
5

私は一連のレコードを保持するドメイン固有のバイナリファイルの検索APIを提供するjavaクラスを使用してclojureで作業しています。clojureから非標準的な反復的なJava APIを使用したInterop

Javaクラスはファイルで初期化され、.nextというメソッドを1つしか持たない内部クラスのインスタンスを返す.queryメソッドを提供します。したがって、通常のJavaコレクションAPIでうまく動作しません。外部クラスも内部クラスも、どのインタフェースも実装していません。

.queryメソッドは、内部クラスの代わりにnullを返すことがあります。 .nextメソッドはレコード文字列を返します。それ以上のレコードが見つからない場合はnullを返します。最初の呼び出しですぐにnullを返すことがあります。

Javaクラスをさらに作成することなく、このJava APIをclojureからうまく機能させるにはどうすればよいですか?

私が思い付くことができる最高は次のとおりです。


(defn get-records 
    [file query-params] 
    (let [tr (JavaCustomFileReader. file)] 
    (if-let [inner-iter (.query tr query-params)] ; .query may return null                
     (loop [it inner-iter 
      results []] 
     (if-let [record (.next it)] 
     (recur it (conj results record)) 
     results)) 
     []))) 

これは私のClojureの配列の抽象化で動作するように、結果のベクトルを与えます。 lazy-seqまたはプロトコルを使用してJava APIからseqを公開する方法はありますか?

+0

これは興味深い質問ですが、非標準Java APIとはどういう意味ですか? – octopusgrabbus

+0

@octopusgrabbus具体的には、Javaコードがjava.util.Iteratorを提供せず、java.lang.Iterableも実装していないことを意味します。論理的には、Javaコードは反復を提供していますが、そのための標準APIへの接続はありません。 –

答えて

4

+0

すてきなソリューション! – Gert

4

Iterableを使用していた場合と同じように、コードは怠惰ではありませんが、lazy-seqでギャップを埋めることができます。

(defn query-seq [q] 
    (lazy-seq 
    (when-let [val (.next q)] 
     (cons val (query-seq q))))) 

おそらく、最初のヌル値から身を守るためにクエリメソッドをラップすることもあります。 lazy-seqに落とすことなく

(defn query [file query] 
    (.query (JavaCustomFileReader. file) query)) 

(defn record-seq [query] 
    (when query 
    (when-let [v (.next query)] 
     (cons v (lazy-seq (record-seq query)))))) 

;; usage: 
(record-seq (query "filename" "query params")) 
+2

'lazy-seq'を' when-let'の周りに動かします。 –

4

lazy-seqのために良いフィットのように思える

(defn record-seq 
    [q] 
    (take-while (complement nil?) (repeatedly #(.next q)))) 

代わりの(complement nil?).nextはブールfalseを返さない場合は、また、単にidentityを使用することができます。

(defn record-seq 
    [q] 
    (take-while identity (repeatedly #(.next q)))) 

また、エントリポイントを少し変更します。

(defn query 
    [rdr params] 
    (when-let [q (.query rdr params)] 
    (record-seq q))) 

(defn query-file 
    [file params] 
    (with-open [rdr (JavaCustomFileReader. file)] 
    (doall (query rdr params)))) 
関連する問題