Clojure中序列的延迟串联

时间:2014-10-27 17:51:13

标签: clojure lazy-evaluation seq

这是一个初学者的问题:在Clojure中有没有办法懒洋洋地连接任意数量的序列?我知道那里有lazy-cat宏,但我无法想到它对任意数量序列的正确应用。

我的用例是通过分页(offseted / limited)请求从API延迟加载数据。通过以下request-fn执行的每个请求都会检索100个结果:

(map request-fn (iterate (partial + 100) 0))

如果没有更多结果,request-fn将返回一个空序列。这是我停止迭代的时候:

(take-while seq (map request-fn (iterate (partial + 100) 0)))

例如,API最多可以返回500个结果,可以模拟为:

(defn request-fn [offset] (when (< offset 500) (list offset)))

如果我想连接结果,我可以使用(apply concat results)但是急切地评估结果序列:

(apply concat (take-while seq (map request-fn (iterate (partial + 100) 0))))

有没有办法如何使用lazy-cat或其他内容懒惰地连接结果序列?

1 个答案:

答案 0 :(得分:9)

对于记录,apply将仅消耗足够的参数序​​列,因为它需要确定为所提供的函数调用哪个arity。由于concat的最大值为3,因此apply最多可以实现基础序列中的3个项目。

如果这些API调用很昂贵并且您实际上无法承担不必要的调用,那么您将需要一个接受seq-of-seq并且一次一个地延迟连接它们的函数。我不认为有任何内置的东西,但编写自己的东西相当简单:

(defn lazy-cat' [colls]
  (lazy-seq
    (if (seq colls)
      (concat (first colls) (lazy-cat' (next colls))))))