I tried the following in Clojure, expecting to have the class of a non-lazy sequence returned:
(.getClass (doall (take 3 (repeatedly rand))))
I stumbled on this this blog post about doall
not being recursive. For that I found the first comment in the post did the trick. Something along the lines of:
(use 'closure.walk)
(postwalk identity nested-lazy-thing)
I found this useful in a unit test where I wanted to force evaluation of some nested applications of map
to force an error condition.
This is to some degree a question of taxonomy. a lazy sequence is just one type of sequence as is a list, vector or map. So the answer is of course "it depends on what type of non lazy sequence you want to get:
Take your pick from:
(doall ... )
(apply list (my-lazy-seq)) OR (into () ...)
(vec (my-lazy-seq))
You can have whatever type of sequence most suites your needs.
This Rich guy seems to know his clojure and is absolutely right.
Buth I think this code-snippet, using your example, might be a useful complement to this question :
=> (realized? (take 3 (repeatedly rand)))
false
=> (realized? (doall (take 3 (repeatedly rand))))
true
Indeed type has not changed but realization has
(.getClass (into '() (take 3 (repeatedly rand))))
doall
is all you need. Just because the seq
has type LazySeq
doesn't mean it has pending evaluation. Lazy seq
s cache their results, so all you need to do is walk the lazy seq
once (as doall
does) in order to force it all, and thus render it non-lazy. seq
does not force the entire collection to be evaluated.