【问题标题】:Interop from clojure a with non-standard iterative java APIclojure a 与非标准迭代 java API 的互操作
【发布时间】:2012-07-09 23:17:08
【问题描述】:

我正在 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))
      [])))

这为我提供了一个与 clojure seq 抽象一起使用的结果向量。是否有其他方法可以从 java API 公开序列,无论是使用惰性序列还是使用协议?

【问题讨论】:

  • 这是一个有趣的问题,但非标准 Java API 是什么意思?
  • @octopusgrabbus 特别是我的意思是Java代码不提供 java.util.Iterator 也不实现 java.lang.Iterable 。从逻辑上讲,java 代码提供了迭代,但没有与标准 API 的连接。

标签: clojure iteration seq clojure-java-interop


【解决方案1】:

不用掉到lazy-seq:

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

如果.next 不返回布尔值false,您也可以只使用identity 而不是(complement nil?)

(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))))

【讨论】:

    【解决方案2】:

    似乎很适合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"))
    

    【讨论】:

      【解决方案3】:

      您的代码并不像使用 Iterable 时那样惰性,但您可以使用惰性序列来填补空白,如下所示。

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

      也许您应该包装查询方法以保护自己免受第一个空值的影响。

      【讨论】:

      • lazy-seq 向上移动到when-let 周围。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-12
      • 1970-01-01
      • 1970-01-01
      • 2019-07-18
      • 1970-01-01
      • 1970-01-01
      • 2014-03-31
      相关资源
      最近更新 更多