Larry Travis <
tra...@cs.wisc.edu> writes:
Hi Larry,
> (1) Is there any way I can extract from a Clojure lazy sequence at
> some given point in its use those of its members that have so far been
> realized? For example, can I extract the cache of realized members,
> turn it into a vector, and then process that vector independently of
> further use of the lazy sequence?
I think, you are looking for `realized?`. Here's a function for
creating a vector of realized elements of a lazy seq.
--8<---------------cut here---------------start------------->8---
user> (defn realized-vec [s]
(loop [s s, r []]
(if (and (seq s) (realized? (rest s)))
(recur (rest s) (conj r (first s)))
(conj r (first s)))))
#'user/realized-vec
user> (def nums (iterate inc 0))
#'user/nums
user> (realized-vec nums)
[0]
user> (take 10 nums)
(0 1 2 3 4 5 6 7 8 9)
user> (realized-vec nums)
[0 1 2 3 4 5 6 7 8 9]
user> (take 15 nums)
(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14)
user> (realized-vec nums)
[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
--8<---------------cut here---------------end--------------->8---
One thing I don't quite understand is why you cannot call `realized?` on
all sequential things. For example, `iterate` is documented to return a
lazy seq, but in fact it creates a Cons whose rest is a lazy seq. Thus,
calling `realized?` on its result errors.
--8<---------------cut here---------------start------------->8---
user> (realized? (iterate inc 1))
; clojure.lang.Cons cannot be cast to clojure.lang.IPending
; [Thrown class java.lang.ClassCastException]
--8<---------------cut here---------------end--------------->8---
So my question is: shouldn't all sequential collections implement
IPending (simply returning true in the case of lists, cons, vector,
...)? Or should `realized?` also test for IPending?
> (2) If I can't extract the cache, is there some way that I can at
> least discover how many realized sequence members have so far been put
> into the cache?
With the function above, that's (comp count realized-vec).
Bye,
Tassilo