Clojure:使用不带头部的流。这是正确的吗?
我想在某处放置一个惰性序列,以便根据需要提供数据。我知道我必须避免抓住镜头的开头。我想出了下面的解决办法,我错过了什么吗Clojure:使用不带头部的流。这是正确的吗?,clojure,lazy-sequences,Clojure,Lazy Sequences,我想在某处放置一个惰性序列,以便根据需要提供数据。我知道我必须避免抓住镜头的开头。我想出了下面的解决办法,我错过了什么吗 (defn headless [s] (let [a (atom s)] (fn ([] (let [s @a r (first s)] (swap! a rest) r)) ([n] (let [s @a rs (take n s)] (swap! a #(drop n %
(defn headless [s]
(let [a (atom s)]
(fn
([] (let [s @a r (first s)]
(swap! a rest) r))
([n] (let [s @a rs (take n s)]
(swap! a #(drop n %)) rs)))))
例如,这个简单的生成器只给出自然数
(def nums (headless (iterate inc 0)))
(nums 5)
; (0 1 2 3 4)
(nums)
;5
更新:“测试”应该使用dorun,而不是doall。见lgrapenthin溶液
一个(不太现实的)测试
(doall (map #(nums %) (repeat 20)))
在使用所有4个内核5分钟后崩溃,但有一个异常(OutOfMemoryError Java heap space)您的代码正常工作
此表格:
(doall (map #(nums %) (repeat 20)))
将产生无限量的(nums 20)并且永远不会返回。您可以使用dorun
来删除生成的(nums 20)
,而不将它们保留在内存中。但是,它不会返回,因为(重复20)
会生成一个无限的惰性seq
稍具可读性的headless版本
(defn headless [s]
(let [a (atom s)]
(fn
([] (let [s @a]
(swap! a rest)
(first s))
([n] (let [s @a]
(swap! a (partial drop n))
(take n s)))))))
啊,所以doall实现了序列,dorun只是运行它。非常感谢。