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