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

时间:2015-12-15 10:40:40

标签: clojure io lazy-evaluation

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

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

Growing heap

似乎这可能与处理文件IO的方式无关,剂量q不应该保留在阅读器的头部。

正如@ joost-diepenmaat指出的那样,这可能与文件IO没有关系,他是对的。

clojure.data.json$write_str.doInvoke

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

2 个答案:

答案 0 :(得分:2)

你可以使用(line-seq rdr)“将rdr中的文本行作为一个懒惰的字符串序列返回”。

答案 1 :(得分:0)

这证明了代码的JSON处理问题而不是文件IO。原帖中的解释。