来自clojure a与非标准迭代java API的互操作

Ale*_*ard 5 iteration clojure seq clojure-java-interop

我在clojure中使用java类,它为包含一系列记录的特定于域的二进制文件提供检索API.

java类用文件初始化,然后提供一个.query方法,该方法返回一个只有一个方法的内部类的实例.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))
      [])))
Run Code Online (Sandbox Code Playgroud)

这给了我一个结果向量来处理clojure seq抽象.是否有其他方法可以使用lazy-seq或使用协议从Java API中公开seq?

kot*_*rak 4

不下降到lazy-seq

(defn record-seq
  [q]
  (take-while (complement nil?) (repeatedly #(.next q))))
Run Code Online (Sandbox Code Playgroud)

相反,(complement nil?)您也可以只使用identityif .nextdoes not return boolean false

(defn record-seq
  [q]
  (take-while identity (repeatedly #(.next q))))
Run Code Online (Sandbox Code Playgroud)

我还会稍微重组一下入口点。

(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))))
Run Code Online (Sandbox Code Playgroud)