这是一个初学者的问题:在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
或其他内容懒惰地连接结果序列?
答案 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))))))