Laziness and Infinite Sequences
Pitfalls: laziness + side effects = surprises (output may never happen if the seq is never realized). Holding the head of a huge lazy seq retains it in memory. Lazy seqs are chunked (realized 32 at a time).
(take 5 (range)) ; (0 1 2 3 4): infinite range
(take 5 (iterate #(* 2 %) 1)) ; (1 2 4 8 16)
(take 4 (cycle [:a :b])) ; (:a :b :a :b)
(take 3 (repeat "x"))
(def fibs (map first (iterate (fn [[a b]] [b (+ a b)]) [0 1])))
(take 10 fibs) ; (0 1 1 2 3 5 8 13 21 34)
(defn primes-from [n] ; a custom lazy sequence
(lazy-seq
(if (every? #(pos? (mod n %)) (range 2 (inc (int (Math/sqrt n)))))
(cons n (primes-from (inc n)))
(primes-from (inc n)))))
(take 10 (primes-from 2)) ; (2 3 5 7 11 13 17 19 23 29)
(realized? (lazy-seq [1])) ; false until consumed
(doall (map println [1 2])) ; force realization (keeps the results)
(dorun (map println [1 2])) ; force realization (discards)
;; iteration (1.11+): consume paginated APIs lazily
(defn fetch-page [token] {:items [token] :next (when (< token 3) (inc token))})
(into [] cat (iteration fetch-page :initk 1 :kf :next :vf :items)) ; [1 2 3]