# Why does this iterator fail to update correctly?

**URL:** <https://discourse.julialang.org/t/why-does-this-iterator-fail-to-update-correctly/74310>\
**Category:** New to Julia\
**Tags:** iterators\
**Created:** [January 9, 2022, 11:10pm UTC](https://discourse.julialang.org/t/why-does-this-iterator-fail-to-update-correctly/74310 "2022-01-09T23:10:43Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![karthink](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/karthink/32/23952_2.png) [@karthink](https://discourse.julialang.org/u/karthink)\
**Post date:** [January 9, 2022, 11:10pm UTC](https://discourse.julialang.org/t/why-does-this-iterator-fail-to-update-correctly/74310/1 "2022-01-09T23:10:44Z")

</div>

This iterator got stuck after the first iteration for me:

Definition:

```julia
struct MyInterval
    trange :: Tuple{Number,Number}
end

function Base.iterate(m::MyInterval, state=m.trange[1])
    if state >= m.trange[2]
        nothing
    else
        mnew = MyInterval(m.trange .+ (0.1, 0))
        (mnew, state+0.1)
    end
end

```

Test:

```julia
M = MyInterval((3,4))
for m in Base.Iterators.take(M,4)
    println(m)
end

```

Output:

```julia
julia> 
MyInterval((3.1, 4))
MyInterval((3.1, 4))
MyInterval((3.1, 4))
MyInterval((3.1, 4))

```

Modifying the iterator update as follows makes it work correctly:

```julia
function Base.iterate(m::MyInterval, state=m.trange[1])
    if state >= m.trange[2]
        nothing
    else
        mnew = MyInterval((state+0.1, m.trange[2]))
        (mnew, state+0.1)
    end
end

```

This differs only in one line:

old: `mnew = MyInterval(m.trange .+ (0.1, 0))`  
new: `mnew = MyInterval((state+0.1, m.trange[2]))`

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 9, 2022, 11:57pm UTC](https://discourse.julialang.org/t/why-does-this-iterator-fail-to-update-correctly/74310/2 "2022-01-09T23:57:34Z")

</div>

> [@karthink](#):
>
> `mnew = MyInterval(m.trange .+ (0.1, 0))`

Your code returns `mnew`, but this doesn’t change the object passed to the next call to `iterate`. The iterator object always stays the same for the whole loop, only `state` changes. The first return value is not a new iterator, but is instead the next element in the collection.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [January 10, 2022, 12:49am UTC](https://discourse.julialang.org/t/why-does-this-iterator-fail-to-update-correctly/74310/3 "2022-01-10T00:49:49Z")

</div>

The iterable instance isn’t typically updated, it usually just holds the minimum information needed to set up the iteration. I can’t tell what your intended output is, so I’ll make one up. Let’s say I want to count upwards from 4 to 7. I just need a struct that contains the first and last integer, and an instance can hold 4 and 7.

`iterate` returns a tuple of the iteration item and iteration state, or it returns `nothing` when iteration is over. The items are the values I want: 4 5 6 7. So `iterate` would return `(4, 1), (5, 2), (6, 3), (7, 4), nothing`.

The state is what is used to keep track of how far the iteration goes. `iterate` does not take in the items, it only takes in the iterable instance and the previous state. In the example above, the previous state determines the result tuple with `(iter.first + state, state + 1)`, though `iter.last` should be used to check if the iteration should end.

The state could have been implemented with different values for a different algorithm.

---

<div class="post-metadata">

**Author:** ![karthink](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/karthink/32/23952_2.png) [@karthink](https://discourse.julialang.org/u/karthink)\
**Post date:** [January 10, 2022, 2:34am UTC](https://discourse.julialang.org/t/why-does-this-iterator-fail-to-update-correctly/74310/4 "2022-01-10T02:34:41Z")

</div>

@stevengj I’m not understanding how that explains the difference between the version that works and the one that doesn’t.

In both cases my code returns `mnew`:

old: `mnew = MyInterval(m.trange .+ (0.1, 0))`  
new: `mnew = MyInterval((state+0.1, m.trange[2]))`

---

<div class="post-metadata">

**Author:** ![sostock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sostock/32/5546_2.png) [@sostock](https://discourse.julialang.org/u/sostock)\
**Post date:** [January 10, 2022, 7:22am UTC](https://discourse.julialang.org/t/why-does-this-iterator-fail-to-update-correctly/74310/5 "2022-01-10T07:22:57Z")

</div>

> [@karthink](#):
>
> In both cases my code returns `mnew` :
> 
> old: `mnew = MyInterval(m.trange .+ (0.1, 0))`  
> new: `mnew = MyInterval((state+0.1, m.trange[2]))`

In the first case, you use the value `m.trange` to create `mnew`, and `m.trange` never changes (in your example it is always `3`), because `m` always refers to the original `MyInterval` instance.

In the second case, you use the value `state` instead of `m.trange`. The `state` changes with every iteration.

---

<div class="post-metadata">

**Author:** ![karthink](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/karthink/32/23952_2.png) [@karthink](https://discourse.julialang.org/u/karthink)\
**Post date:** [February 22, 2022, 3:21am UTC](https://discourse.julialang.org/t/why-does-this-iterator-fail-to-update-correctly/74310/6 "2022-02-22T03:21:22Z")

</div>

Thanks to everyone for explaining. This took me a while to wrap my head around.
