# \`peek\` seems to consume iterator elements?

**URL:** https://discourse.julialang.org/t/peek-seems-to-consume-iterator-elements/98878
**Category:** New to Julia
**Created:** [May 15, 2023, 12:37pm UTC](https://discourse.julialang.org/t/peek-seems-to-consume-iterator-elements/98878 "2023-05-15T12:37:01Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![frylock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frylock/32/50213_2.png) [@frylock](https://discourse.julialang.org/u/frylock)
#### Post date: [May 15, 2023, 12:37pm UTC](https://discourse.julialang.org/t/peek-seems-to-consume-iterator-elements/98878/1 "2023-05-15T12:37:01Z")

</div>

```julia
using Base.Iterators

a = collect("abbcccddddeeeee")
b = Base.Iterators.Stateful(a)

while !isempty(b)
    c = peek(b)
    println(collect(takewhile(x -> x == c, b)))
end

```

I’m trying to learn about Julia stateful iterators, and tried out the above code. I was expecting to see printed out `['a']` on a line by itself, `['b', 'b']` on a line by itself, etc., however, what I got out was:

```julia
['a']
['b']
['c', 'c']
['d', 'd', 'd']
['e', 'e', 'e', 'e']

```

It would seem that the `peek` call didn’t consume an iterator element the first time around, but did consume an element every time after that?

---

<div class="post-metadata">

### Author: ![barucden](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barucden/32/26154_2.png) [@barucden](https://discourse.julialang.org/u/barucden)
#### Post date: [May 15, 2023, 12:38pm UTC](https://discourse.julialang.org/t/peek-seems-to-consume-iterator-elements/98878/2 "2023-05-15T12:38:58Z")

</div>

I think it is due to `takewhile`, not `peek`:

> <https://github.com/JuliaLang/julia/issues/48195>
>
> To me, it's clear that the intended behaviour aught to be that calling \`Iterator…s.takewhile\` on a Stateful Iterator should return all leading matching elements, and leave the Stateful Iterator with all remaining elements. 
> 
> One possible solution would be to use \`peek\` for \`takewhile\` if the iterator is Stateful, rather than \`iterate\` as seen here,
> https://github.com/JuliaLang/julia/blob/53a0a69f56ded710fae2b17a33e571aa4714a80a/base/iterators.jl#L856-L861
> 
> I'm not certain if this can be applied to the generic implementation as a zero-cost abstraction, or if it would be better handled through multiple dispatch and a more specific method for Stateful Iterators. 
> 
> I suspect that a similar issue is affecting list comprehensions and Stateful Iterators. I haven't tested that myself, but in my research regarding this issue, I saw several people bringing up a similar complaint.

---

<div class="post-metadata">

### Author: ![frylock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frylock/32/50213_2.png) [@frylock](https://discourse.julialang.org/u/frylock)
#### Post date: [May 15, 2023, 12:47pm UTC](https://discourse.julialang.org/t/peek-seems-to-consume-iterator-elements/98878/3 "2023-05-15T12:47:34Z")

</div>

Oh … I guess I was expecting something similar to Racket’s [takef](https://docs.racket-lang.org/reference/pairs.html#%28def._%28%28lib._racket%2Flist..rkt%29._takef%29%29) function (i.e. doesn’t consume first non-matching).

Is there a different iterator constructor in Julia that I could use that would not have the “consume first non-matching” behavior?

---

<div class="post-metadata">

### Author: ![barucden](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barucden/32/26154_2.png) [@barucden](https://discourse.julialang.org/u/barucden)
#### Post date: [May 15, 2023, 1:47pm UTC](https://discourse.julialang.org/t/peek-seems-to-consume-iterator-elements/98878/4 "2023-05-15T13:47:46Z")

</div>

My understanding is that this behavior is not exactly desirable; it may even be a bug. So I don’t think there is a `takewhile` for stateful iterators that doesn’t consume the first non-matching element.

One way around is to implement the behavior yourself. For example, the following should give you what you expected:

```julia
julia> while !isempty(b)
           c = peek(b)
           xs = []
           while !isempty(b) && peek(b) == c
               push!(xs, popfirst!(b))
           end
           println(xs)
       end

```

---

<div class="post-metadata">

### Author: ![frylock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frylock/32/50213_2.png) [@frylock](https://discourse.julialang.org/u/frylock)
#### Post date: [May 15, 2023, 2:09pm UTC](https://discourse.julialang.org/t/peek-seems-to-consume-iterator-elements/98878/5 "2023-05-15T14:09:11Z")

</div>

Yours is more elegant than mine, but that is what I had come up with.
