clojure - 当需要处理 seq 两次时,如何实现不保留头部的惰性 seq?

标签 clojure

当一个函数被赋予一个大的惰性序列时,避免保留头部是有益的,这样在完全实现的序列不适合内存的情况下,您仍然可以处理它。例如,这工作正常:

(count (take 10000000 (range)))
(reduce + (take 10000000 (range)))

但这可能会产生内存不足错误:

(defn recount [coll n]
  [(count (take n coll))
   (reduce + (take n coll))])
(recount (range) 10000000)

因为count实现lazy seq时,coll的绑定(bind)保留了序列的头部。

我能想到的最接近的是一个强制重新评估 seq 而不是绑定(bind)的宏:

(defmacro recount4 [coll n]
  `[(count (take ~n ~coll))
    (reduce + (take ~n ~coll))])
(recount4 (range) 10000000)

这似乎并不广泛适用。

我查看了this blog ,但由于使用原子和可变状态,该解决方案不太令人满意。

最佳答案

您可能想查看eduction - 它创建一个延迟的、非缓存的顺序集合,并将在每次使用时通过缩减重新评估完整集合。

关于clojure - 当需要处理 seq 两次时,如何实现不保留头部的惰性 seq?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41309994/

相关文章:

clojure - 确保在所有请求完成后关闭 clj-http 连接管理器的正确方法

core.matrix 中的矩阵乘法

clojure - 如何在 core.logic 中编写自己的简单约束函数?

clojure - 惯用的 clojure 从字符串中解析命令行开关和参数

clojure - Clojure 中 definterface 和 defprotocol 的区别

clojure - 如何在 clojure 中实习宏?

Clojure:从模板生成函数

clojure - 在clojure中构建sitemap.xml?

python - Python 中 Clojure 的 "assoc-in"和 "get-in"的等价物

java - 使用 Clojure 需要哪些 Java 组件?