如何将 java Iterator-like 对象转换为 clojure 序列

发布于 2025-01-04 11:32:27 字数 440 浏览 2 评论 0原文

我正在使用 Sesame 库通过内存中的三元组存储运行 SPARQL 查询。

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

查询结果是一个类似自定义迭代器的 [1] 对象,因此 clojure seq 无法立即对其进行处理。

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

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

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

I'm using the Sesame library to run SPARQL queries over an in-memory triple store.

I am using Clojure to achieve this.

A query result is a custom Iterator-like [1] object, so the clojure seq does not work on it out of the box.

What is the most elegant way to turn a custom java Iterator like object into a clojure sequence?

The most obvious and dumb idea that has come to my mind is to loop over it and build up a clojure vector, but I'm sure there is more elegant approach to this problem.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

魔法少女 2025-01-11 11:32:27

测试版本:

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

The tested version:

(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)))))))
池木 2025-01-11 11:32:27

将类似迭代器的对象包装在实际实现 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 中无论如何都不会使用这些异常。

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

How about wrapping the iterator-like object in an object that actually implements the Iterator interface? Something like the following (not tested):

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

As far as I can tell, the only advantage (if you want to call it that) of the Iteration interface over the standard Iterator interface is that it allows to declare checked exceptions, which are not used in Clojure anyways.

[Update: Corrected code to use iterator-seq instead of seq, as suggested by @amalloy in a comment on another answer.]

一百个冬季 2025-01-11 11:32:27

为什么不尝试 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 中的序列?

Why not give clojure.core/iterator-seq a try?

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.

As you can see in the docstring above, you might not even need to use iterator-seq explicitly. Did you just try treating your Java iterator as a sequence in the REPL?

贪了杯 2025-01-11 11:32:27

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

优点是它是纯函数式的,因为它采用 iterable 作为参数。其他发布的解决方案采用可变的迭代器参数,因此函数可能会根据内部迭代器状态返回不同的序列,这违反了 引用透明度
该函数还夸大了它的惰性。

Pure functional iterable-to-lazy-sequence code for java Iterable and Iterator

(defn iter-seq
  ([iterable] 
    (iter-seq iterable (.iterator iterable)))
  ([iterable i] 
    (lazy-seq 
      (when (.hasNext i)
        (cons (.next i) (iter-seq iterable i))))))

For custom iterators replace .iterator, .hasNext and .next calls.

The advantage is that it's purely functional since it takes iterable as an argument. Other posted solutions take iterator argument which is mutable so the function may return a different sequence depending on internal iterator state what violates referential transparency.
The function is also flamboyant about its laziness.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文