Understanding futures and doall in Clojure -
i came across example on futures in clojure example
(let [sleep-and-wait (map (fn [time] (future (thread/sleep time) (println (str "slept " time " sec" )))) [4000 5000])] (doall (map deref sleep-and-wait)) (println "done"))
since map
produces lazy sequence expect future
not started, until call deref
on it. deref
expected block until future returns result. map
elements sequentially, expected code run 9 sec, runs in 5.
could explain why?
clojure lazy-seqs make no promise maximally lazy.
+user=> (take 1 (for [i (range 1000)] (doto (println " - printed")))) (0 - printed 1 - printed 2 - printed 3 - printed 4 - printed 5 - printed 6 - printed 7 - printed 8 - printed 9 - printed 10 - printed 11 - printed 12 - printed 13 - printed 14 - printed 15 - printed 16 - printed 17 - printed 18 - printed 19 - printed 20 - printed 21 - printed 22 - printed 23 - printed 24 - printed 25 - printed 26 - printed 27 - printed 28 - printed 29 - printed 30 - printed 31 - printed 0)
when seq called on vector (most lazy operations implicitly call seq on collection argument), produces chunked data type, realizes batches of results @ time, instead of 1 one. if need control consumption of data, can forces unchunking.
+user=> (defn unchunk [s] (when (seq s) (lazy-seq (cons (first s) (unchunk (rest s)))))) #'user/unchunk +user=> (take 1 (for [i (unchunk (range 1000))] (doto (println " - printed")))) (0 - printed 0)
of course, simpler option in case use type isn't chunked
+user=> (take 1 (for [i (take 1000 (iterate inc 0))] (doto (println " - printed")))) (0 - printed 0)
Comments
Post a Comment