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]