我想在某处放置一个惰性序列以根据需要提供数据。我知道我必须避免保持序列的头部。我提出了以下解决方案,我错过了什么吗?
(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)))
使用异常(OutOfMemoryError Java堆空间)使用所有4个核心5分钟后崩溃
答案 0 :(得分:2)
您的代码有效。
此表格:
(doall (map #(nums %) (repeat 20)))
将产生无限量(nums 20)并且永不返回。您可以使用dorun
来删除生成的(nums 20)
,而不是将其保留在内存中。但是,它不会返回,因为(repeat 20)
生成一个无限的懒惰序列。
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)))))))