On Jan 22, 9:08 am, Konrad Hinsen <konrad.hin...@laposte.net> wrote:
> On 21.01.2009, at 20:33, Rich Hickey wrote:
>
> > I've started documenting the streams work I have been doing, for those
> > interested:
>
> >http://clojure.org/streams
>
> Nice!
>
> I have played a bit with the stream implementation, and I came across
> a behaviour that I do not understand:
>
> First, define a random stream that calls rand, and an iter on it:
>
>         (def rand-stream (stream (fn [_] (rand))))
>         (def rand-iter (stream-iter rand-stream))
>
> Calling it a few times shows that it works:
>
>         (next! rand-iter nil)
>         (next! rand-iter nil)
>
> Next, try to use it as a seq:
>
>         (take 4 rand-stream)
>
> This fails, as it should:
>
>         java.lang.IllegalStateException: Already iterating (NO_SOURCE_FILE:0)
>
> Detach the iter and try again:
>
>         (detach! rand-iter)
>         (take 4 rand-stream)
>
> Now it works - fine. But what happened to the seq that now owns the
> stream? Nothing refers to it, so it should be gone.

No, the stream must refer to it, in order to keep its promise to
return the same seq every time.

> Did it perhaps
> liberate the stream, so that I can create an iter again? Let's try:
>
>         (def rand-iter (stream-iter rand-stream))
>         (next! rand-iter nil)
>         (next! rand-iter nil)
>
> It seems so. But... let's be mean:
>
>         (take 4 rand-stream)
>
> I would expect this to throw the IllegalStateException again, but it
> doesn't: it returns the same four-number sequence as the last time it
> was called. Where was that one stored? In the stream itself? Or does
> the stream keep a reference to the seq, so that it never disappears?
> But then I shouldn't be able to create another iterator.

What you've created an iter on the second time is the seq of the
stream. Right now, once you've treated a stream as a seq it will
always behave like one. So this second stream-iter call actually
creates an iter on a stream on that seq.

>
> Let's be mean again:
>
>         (next! rand-iter nil)
>         (take 10 rand-stream)
>         (next! rand-iter nil)
>         (next! rand-iter nil)
>         (take 15 rand-stream)
>
> All of these work - it seems I have both an iter and a seq on the
> same stream, with the iter returning values that are also in the seq.
>

No, you've got a generator, a stream on that, a seq on that, a stream
on that seq and an iter on that stream - that's why you are getting
the same values. You'll never have a seq and an iter on the same
generator, i.e. interleaved values.

I understand this may not be intuitive or clear yet from the docs. Nor
am I set in this being the behavior. The case I am looking towards is
this one:

(def s (stream (range 10)))
(if (seq s)
  (take 4 (map-stream inc s))

A stream is used as a seq and then passed to a stream function.
Without this seqed-stream-behaves-as-seq capability, this will fail
with Already iterating, and would have to be written:

(if (seq s)
  (take 4 (map-stream inc (seq s))))

Rich

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to