I wondered: What happens when you embed an expression that forces realization of a lazy sequence inside of an outer lazy sequence that's not realized?
Answer: It seems to depend on how you create the outer lazy sequence. If the outer sequence comes from map
, the inner sequence is realized, and if the outer sequence comes for iterate
, it's not.
Well, I'm pretty sure that that is not the right way to describe what happens below--I'm pretty sure that I'm not understanding something. Can someone explain?
(There is one quirk, which is that while map
returns a LazySeq
, iterate
returns a Cons
wrapped around a LazySeq
. So in the tests for class and realization below, I look at the rest
of the output of iterate
. I don't believe that this difference between map
and iterate
has anything to do with my question.)
(def three-vec (range 1 4))
(defn print-times-10-ret [x]
(let [y (* 10 x)]
(println "[" y "] " )
y))
(defn once [xs] (map print-times-10-ret xs))
(defn doall-once [xs] (doall (map print-times-10-ret xs)))
(defn doa-twice [xs] (once (doall-once xs))) ; "doa" since only half doall-ed
;; Here the inner sequence seems to get realized:
(def doa-twice-map (doa-twice three-vec))
; printed output:
; [ 10 ]
; [ 20 ]
; [ 30 ]
;; Here we create a lazy sequence that will call doall-once when
;; realized, but nothing gets realized:
(def doall-once-iter (iterate doall-once three-vec))
; no printed output
(class doa-twice-map)
; => clojure.lang.LazySeq
;; Note that this is not realized, even though the inner seq was realized (?):
(realized? doa-twice-map)
; => false
(class (rest doall-once-iter))
; => clojure.lang.LazySeq
(realized? (rest doall-once-iter))
; => false