5

私は、一連のレコードを保持するドメイン固有のバイナリ ファイルの取得 API を提供する Java クラスを使用して、clojure で作業しています。

Java クラスはファイルで初期化され、.queryメソッドを 1 つしか持たない内部クラスのインスタンスを返すメソッドを提供する.nextため、通常の 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 seq 抽象化を操作するための結果のベクトルが得られます。lazy-seqまたはプロトコルを使用して、Java APIからseqを公開する他の方法はありますか?

4

3 に答える 3

4

にぴったりのようです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"))
于 2012-07-10T17:59:04.500 に答える
4

にドロップせずにlazy-seq:

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

代わりに、ブール値を返さない場合(complement nil?)に使用することもできます。identity.nextfalse

(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))))
于 2012-07-11T06:17:12.550 に答える
4

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

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

おそらく、クエリ メソッドをラップして、最初の null 値からも保護する必要があります。

于 2012-07-10T17:44:40.707 に答える