2014-10-27 20 views
7

這裏有一個初學者的問題:在Clojure中是否有一種方法來懶散地連接任意數量的序列?我知道有lazy-cat宏,但我不能想到它的正確應用程序的任意數量的序列。Clojure中序列的懶串聯

我的用例是通過paginated(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

['lazy-cat' *宏*](http://grimoire.arrdem.com/1.6。 0/clojure.core/lazy-cat /)只根據需要評估每個參數。 – Thumbnail 2014-10-27 19:04:23

+0

是的,但是你如何將它應用於一系列參數? – 2014-10-27 19:06:54

+0

你真的需要連接結果嗎,還是隻是想懶惰地消耗它們? – 2014-10-27 19:12:01

回答

8

爲了記錄,apply將僅消耗足夠的參數序​​列,因爲它需要確定要調用哪個參數來提供所提供的功能。由於concat的最大秩序爲3,apply將實現最多3個來自基礎序列的項目。

如果這些API調用非常昂貴,而且您真的無法承擔不必要的調用,那麼您將需要一個接受seq-of-seqs並且一次一個地連接它們的函數。我不認爲有任何內置的,但它是相當簡單的寫你自己的:

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

謝謝你的申請的澄清和懶貓的建議'。 – 2014-10-27 19:25:48

+0

不錯的答案;順便說一句,當使用'next'時,即使只需要1次評估,這個函數也會從'colls'中熱切評估2個項目,例如。 '(第一(懶貓貓'aseq))'。使用rest來代替預期的行爲。 – pestrella 2017-07-28 12:50:44