# Iteration over OrdinalRange

**URL:** <https://discourse.julialang.org/t/iteration-over-ordinalrange/23569>\
**Category:** General Usage\
**Tags:** question\
**Created:** [April 26, 2019, 4:59pm UTC](https://discourse.julialang.org/t/iteration-over-ordinalrange/23569 "2019-04-26T16:59:11Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![jonas-kr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jonas-kr/32/1810_2.png) [@jonas-kr](https://discourse.julialang.org/u/jonas-kr)\
**Post date:** [April 26, 2019, 4:59pm UTC](https://discourse.julialang.org/t/iteration-over-ordinalrange/23569/1 "2019-04-26T16:59:11Z")

</div>

Playing around with iterators I noticed that calling

```julia
iterate(1:5, 1)

```

yields in

```julia
(2, 2)

```

while

```julia
iterate(collect(1:5), 1)

```

yields in

```julia
(1, 2)

```

as I would expect it to.  
To the best of my knowledge, iterate is supposed to return a tuple containing the next element and the new iteration state. However, its definition for elements of type OrdinalRange returns a tuple (new state, new state). Does anyone know what’s the reasoning behind this?

Thank you very much in advance!

**EDIT:**  
Further, it seems strange that

```julia
iterate(1:5, 0)

```

and

```julia
iterate(1:5)

```

are equivalent, while for “normal” arrays

```julia
iterate(collect(1:5), 1)

```

and

```julia
iterate(collect(1:5))

```

yield the same result.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [April 26, 2019, 9:01pm UTC](https://discourse.julialang.org/t/iteration-over-ordinalrange/23569/2 "2019-04-26T21:01:26Z")

</div>

The answer here is simply that the `state` is an implementation detail. You can’t expect that the first next state of an object is going to be the number `1`. Instead, you need to ask the object what its next state is with the one-argument `iterate`:

```julia
julia> iterate(1:5)
(1, 1)

julia> iterate(collect(1:5))
(1, 2)

julia> iterate(Dict(1=>2))
(1 => 2, 17)

julia> iterate(Dict(1=>2, 3=>4))
(3 => 4, 8)

```

Manually choosing a state to pass to `iterate` can be dangerous as you might be giving it something that’s completely invalid and it didn’t expect. In general, you don’t want to touch iteration states — you just pass them along.

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [April 26, 2019, 9:01pm UTC](https://discourse.julialang.org/t/iteration-over-ordinalrange/23569/3 "2019-04-26T21:01:42Z")

</div>

This is because `UnitRange` (such as `1:5`) and `Vector` (such as `collect(1:5)`) do not define their “iterator state” in the same way.

The documentation for the [iterators interface](https://docs.julialang.org/en/v1/manual/interfaces/) explains that

```julia
for i in iter
    # body
end

```

gets translated into

```julia
next = iterate(iter)
while next !== nothing
    (i, state) = next
    # body
    next = iterate(iter, state)
end

```

In other words, the first call to `iterate` is performed with only one argument and returns an `(element, state)` tuple. The `state` from each call is passed as the second argument in the next call to `iterate`. But the `iterate` method for each type can decide exactly how the state is represented.

Let’s look at what happens in both cases you mention:

```julia
function test_iter(collection)
    @show next = iterate(collection)
    while next !== nothing
        (i, state) = next
        @show next = iterate(collection, state)
    end
end

```

```julia
julia> test_iter(1:5)
next = iterate(collection) = (1, 1)
next = iterate(collection, state) = (2, 2)
next = iterate(collection, state) = (3, 3)
next = iterate(collection, state) = (4, 4)
next = iterate(collection, state) = (5, 5)
next = iterate(collection, state) = nothing

```

```julia
julia> test_iter(collect(1:5))
next = iterate(collection) = (1, 2)
next = iterate(collection, state) = (2, 3)
next = iterate(collection, state) = (3, 4)
next = iterate(collection, state) = (4, 5)
next = iterate(collection, state) = (5, 6)
next = iterate(collection, state) = nothing

```

In both cases, the `state`s are consecutive indices. But states in the `Vector` case are shifted by 1 w.r.t. states in the `UnitRange` case. This explains both your observations: the state associated to the first element (i.e. the implicit state that is omitted in the first call to `iterate`) in a `UnitRange` is 0, whereas the state associated to the first element in a vector is 1.

Does this make sense?

  

EDIT: it looks like I posted almost simultaneously to `mbauman`. Keeping this answer anyway in case it would add something to his excellent answer…

---

<div class="post-metadata">

**Author:** ![jonas-kr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jonas-kr/32/1810_2.png) [@jonas-kr](https://discourse.julialang.org/u/jonas-kr)\
**Post date:** [April 28, 2019, 8:43pm UTC](https://discourse.julialang.org/t/iteration-over-ordinalrange/23569/4 "2019-04-28T20:43:42Z")

</div>

Thank you very much for your replies! Now, I do understand what’s happening in both cases.
