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