【问题标题】:What is the idiomatic way of iterating over a lazy sequence in Clojure?在 Clojure 中迭代惰性序列的惯用方式是什么?
【发布时间】:2015-12-15 10:40:39
【问题描述】:

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

(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 不应该抓住读者的头。

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

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

【问题讨论】:

  • “这样做的明显缺点是急切地处理文件导致堆溢出。”为什么会这样?另外:line-seq 是内置的。
  • @JoostDiepenmaat 不确定我可能错了。我正在启用 Java Mission Control 并检查发生了什么。

标签: clojure io lazy-evaluation


【解决方案1】:

您可以使用(line-seq rdr),它“将来自 rdr 的文本行作为惰性字符串序列返回”。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2013-04-22
      • 2023-03-21
      • 2011-02-26
      • 2013-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多