How do turn a java Iterator-like object into a clojure sequence
我正在使用Sesame库在内存中的三元存储上运行SPARQL查询。
我正在使用Clojure实现此目的。
查询结果是自定义迭代器-like [1]对象,因此clojure seq不能立即使用。
将自定义java Iterator这样的对象转换为clojure序列的最优雅方法是什么?
我想到的最明显,最愚蠢的想法是遍历它并建立clojure向量,但是我敢肯定有解决这个问题的更优雅的方法。
[1] http://www.openrdf.org/doc/sesame2/api/info/aduna/iteration/Iteration.html
经过测试的版本:
1 2 3 4 5 6 7 8 | (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))))))) |
如何将类似迭代器的对象包装在实际实现
1 2 3 4 5 6 | (defn iteration-seq [iteration] (iterator-seq (reify java.util.Iterator (hasNext [this] (.hasNext iteration)) (next [this] (.next iteration)) (remove [this] (.remove iteration))))) |
据我所知,
[更新:已更正的代码使用
为什么不尝试clojure.core / iterator-seq?
1 2 3 4 5 6 | 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. |
如您在上面的文档字符串中所见,您甚至可能不需要显式使用
用于Java Iterable和Iterator的纯功能性可迭代到延迟序列代码
1 2 3 4 5 6 7 | (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调用。
的优点是它纯粹是功能性的,因为它将可迭代作为参数。其他发布的解决方案采用可变的迭代器参数,因此该函数可能会根据内部迭代器状态(违反引用透明性)而返回不同的序列。该功能还很懒惰。