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只是运行它。非常感谢。