未實現懶-seq的一步,我有一個懶序列,其中每個項目需要一定的時間來計算:我可以處理的步驟
(defn gen-lazy-seq [size]
(for [i (range size)]
(do
(Thread/sleep 1000)
(rand-int 10))))
是否有可能評估一步此序列步驟並打印結果。當我試着使用for
或doseq
Clojure的處理總是實現整體懶-seq的打印任何東西之前:
(doseq [item (gen-lazy-seq 10)]
(println item))
(for [item (gen-lazy-seq 10)]
(println item))
兩個表達式將等待10秒打印任何東西之前。我曾將doall和dorun看作解決方案,但他們要求lazy-seq生成函數包含println。我想分別定義一個lazy-seq生成函數和lazy-seq打印函數,並使它們逐項地一起工作。
試圖執行此操作的動機: 我有通過網絡進入的消息,並且我希望在收到所有消息之前開始處理它們。同時,將所有對應於查詢的消息保存在lazy-seq中將會很好。
編輯1:
JohnJ的回答顯示瞭如何創建一個懶惰-seq的,將被評估一步一步來。我想知道如何逐步評估任何懶惰seq。
我很困惑,因爲在上面定義的gen-lazy-seq上運行(chunked-seq? (gen-lazy-seq 10))
,或者如JohnJ的答案中定義的那樣都返回false。那麼問題不可能是一個創建了一個分塊的序列,另一個沒有。
在this答案中,顯示了將分塊lazy-seq變成非分塊的函數的函數seq1。嘗試該功能仍然會導致延遲輸出的相同問題。我想,也許延遲已與某種在REPL緩衝要做,所以我試圖同時打印時在SEQ每個項目實現時間:
(defn seq1 [s]
(lazy-seq
(when-let [[x] (seq s)]
(cons x (seq1 (rest s))))))
(let [start-time (java.lang.System/currentTimeMillis)]
(doseq [item (seq1 (gen-lazy-seq 10))]
(let [elapsed-time (- (java.lang.System/currentTimeMillis) start-time)]
(println "time: " elapsed-time "item: " item))))
; output:
time: 10002 item: 1
time: 10002 item: 8
time: 10003 item: 9
time: 10003 item: 1
time: 10003 item: 7
time: 10003 item: 2
time: 10004 item: 0
time: 10004 item: 3
time: 10004 item: 5
time: 10004 item: 0
與JohnJ的版本做同樣的事GEN-懶-seq的作品如預期
; output:
time: 1002 item: 4
time: 2002 item: 1
time: 3002 item: 6
time: 4002 item: 8
time: 5002 item: 8
time: 6002 item: 4
time: 7002 item: 5
time: 8002 item: 6
time: 9003 item: 1
time: 10003 item: 4
編輯2:
這是與它有這個問題產生的不僅序列。地圖生成該序列不能被處理步步無論SEQ1包裝的:
(defn gen-lazy-seq [size]
(map (fn [_]
(Thread/sleep 1000)
(rand-int 10))
(range 0 size)))
但是該序列中,也與圖創建的工作原理:
(defn gen-lazy-seq [size]
(map (fn [_]
(Thread/sleep 1000)
(rand-int 10))
(repeat size :ignored)))
我也試過'seq1',並沒有設法使它與Clojure 1.5或1.2.1一起工作。這可能是因爲你在實現'for'宏時遇到了一些特殊情況,這是一種透明的東西,你不能簡單地通過將它封裝在你自己的懶惰seq中來關閉它。 – JohnJ
感謝您的測試。這似乎是合理的問題是由於。我試圖用地圖創建一個lazy-seq,並按預期工作。 – snowape
再測試一下,似乎我和map生成的序列有同樣的問題。 – snowape