在 Clojure 中迭代惰性序列的惯用方法是什么?

What is the idiomatic way of iterating over a lazy sequence in Clojure?

我有以下函数来处理具有恒定内存使用量的大文件。

(defn lazy-helper
    "Processes a java.io.Reader lazily"
    [reader]
    (lazy-seq
          (if-let [line (.readLine reader)]
                  (cons line (lazy-helper reader))
                  (do (.close reader) nil))))
(defn lazy-lines
    "Return a lazy sequence with the lines of the file"
    [^String file]
    (lazy-helper (io/reader file)))

当处理部分是过滤或其他与惰性序列一起工作的映射或减少操作时,这非常有效。

当我处理文件并例如通过通道将每一行发送到工作进程时,问题就开始了。

(thread
  (doseq [line lines]
    (blocking-producer work-chan line)))

这样做的明显缺点是急切地处理文件导致堆溢出。

我想知道遍历文件中的每一行并对这些行执行一些 IO 的最佳方法是什么。

这似乎与文件 IO 的处理方式无关,doseq 不应该抓住 reader 的头部。

正如@joost-diepenmaat 所指出的,这可能与文件 IO 无关,他是对的。

看来我使用 JSON 序列化和反序列化的方式是这里的根本原因。

您可以使用 (line-seq rdr) 其中 "returns the lines of text from rdr as a lazy sequence of strings"。

这原来是 JSON 处理代码而不是文件 IO 的问题。原文中的解释post.