13

我正在使用 Sesame 库在内存三重存储上运行 SPARQL 查询。

我正在使用 Clojure 来实现这一点。

查询结果是一个自定义的类似迭代器的 [1] 对象,因此 clojure seq不能直接使用它。

将自定义 java Iterator 类对象转换为 clojure 序列的最优雅方法是什么?

我想到的最明显和最愚蠢的想法是循环它并建立一个clojure向量,但我相信这个问题有更优雅的方法。

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

4

4 回答 4

10

测试版:

(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)))))))
于 2012-02-10T18:02:44.103 回答
7

将类似迭代器的对象包装在实际实现Iterator接口的对象中怎么样?类似于以下内容(未测试):

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

据我所知,与Iteration标准Iterator接口相比,该接口的唯一优势(如果您想这样称呼它)是它允许声明已检查的异常,而这在 Clojure 中无论如何都不会使用。

[更新:如@amalloy 在对另一个答案的评论中所建议的那样,更正了使用iterator-seq而不是 的代码。]seq

于 2012-02-10T10:54:54.490 回答
2

为什么不试试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显式使用。您是否只是尝试将您的 Java 迭代器视为 REPL 中的一个序列?

于 2013-07-07T19:54:09.067 回答
2

java Iterable 和 Iterator 的纯函数式可迭代到惰性序列代码

(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 调用。

优点是它纯粹是功能性的,因为它需要可迭代作为参数。其他发布的解决方案采用可变的迭代器参数,因此函数可能会根据内部迭代器状态返回不同的序列,这违反了引用透明性。该功能也因其懒惰而华丽。

于 2013-03-26T00:33:38.710 回答