# Difference between calling Iterators.rest on an array vs a range

**URL:** https://discourse.julialang.org/t/difference-between-calling-iterators-rest-on-an-array-vs-a-range/96533
**Category:** New to Julia
**Tags:** question, iterators
**Created:** [March 23, 2023, 8:10pm UTC](https://discourse.julialang.org/t/difference-between-calling-iterators-rest-on-an-array-vs-a-range/96533 "2023-03-23T20:10:42Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![phantom](https://avatars.discourse-cdn.com/v4/letter/p/e0b2c6/32.png) [@phantom](https://discourse.julialang.org/u/phantom)
#### Post date: [March 23, 2023, 8:10pm UTC](https://discourse.julialang.org/t/difference-between-calling-iterators-rest-on-an-array-vs-a-range/96533/1 "2023-03-23T20:10:42Z")

</div>

I’m just curious why `Iterators.rest` yields different results depending on whether a range or an array is used. eg

```julia
df1 = DataFrame( :x=> 1:5) 

```

To start a loop on the second iteration of a range I would use

```julia

collect(Iterators.rest(eachindex(df1.x),1)) # state = 1
4-element Vector{Int64}:
 2
 3
 4
 5

```

The example in the [docs](https://docs.julialang.org/en/v1/base/iterators/) use an array, and to start on the second iteration of an array would be

```julia
collect(Iterators.rest(collect(eachindex(df1.x)),2)) # state = 2
4-element Vector{Int64}:
 2
 3
 4
 5

```

I was just wondering what accounts for the difference?

---

<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: [March 23, 2023, 11:46pm UTC](https://discourse.julialang.org/t/difference-between-calling-iterators-rest-on-an-array-vs-a-range/96533/2 "2023-03-23T23:46:36Z")

</div>

Minor but important point, you’re not looking at the range, you’re looking at its indices `eachindex`, which in this case is a `Base.OneTo(5)`. But if you remove that method call, this discrepancy remains.

The main point here is that state is not an iteration count or the corresponding item. See how the first two items below (1,2) are the same for the range and the array, but the states are different? Although states indicate iteration progress, there’s no expectation we can intuit the state that produces the n-th iteration. The state can actually be anything, even strings\*.

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

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

```

\*unintuitive strings as state

```julia
struct HelloWorld end

function Base.iterate(::HelloWorld, state=nothing)
  if state == "ZA"
    ("WORLD!", "STOP TIME")
  elseif state == "STOP TIME" # no more items
    nothing
  else # unexpected or no states start at Hello
    ("Hello ", "ZA")
  end
end

for i in HelloWorld() println(i) end # Hello WORLD!
println(iterate(HelloWorld(), "whoops")) # ("Hello ", "ZA")
println(iterate(HelloWorld(), "ZA")) # ("WORLD!", "STOP TIME")
println(iterate(HelloWorld(), "STOP TIME")) # nothing

```

---

<div class="post-metadata">

### Author: ![Liozou](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/liozou/32/35118_2.png) [@Liozou](https://discourse.julialang.org/u/Liozou)
#### Post date: [March 24, 2023, 2:58pm UTC](https://discourse.julialang.org/t/difference-between-calling-iterators-rest-on-an-array-vs-a-range/96533/3 "2023-03-24T14:58:23Z")

</div>

As stated above, `Iterators.rest` takes a `state` as its second argument, which is usually an implementation detail of the iterator. It so happens that `state=1` does not refer to the same iteration point for a range and a vector. `Iterators.rest` should mostly be used on the iterators that you define, since the iteration `state` is otherwise not usually part of any API.  
If you are curious and want to look at the definition of `iterate` for ranges and for vectors, you can type `@edit iterate(1:5)` and `@edit iterate([3, 5, 6])` in your REPL and look at the code. The full iteration protocol is detailed in the docs [here](https://docs.julialang.org/en/v1/manual/interfaces/) and [there](https://docs.julialang.org/en/v1/base/collections/#lib-collections-iteration).

In contrast, the user-facing `Iterators.drop` does not rely on the internals of the iteration protocol and can be used to skip the `n` first elements, as you would expect. With your examples, when dropping `1` element (i.e. starting at the second element of the iterator):

```julia
julia> collect(Iterators.drop(1:5, 1))
4-element Vector{Int64}:
 2
 3
 4
 5

julia> collect(Iterators.drop(collect(1:5), 1))
4-element Vector{Int64}:
 2
 3
 4
 5

```

---

<div class="post-metadata">

### Author: ![phantom](https://avatars.discourse-cdn.com/v4/letter/p/e0b2c6/32.png) [@phantom](https://discourse.julialang.org/u/phantom)
#### Post date: [March 24, 2023, 5:33pm UTC](https://discourse.julialang.org/t/difference-between-calling-iterators-rest-on-an-array-vs-a-range/96533/4 "2023-03-24T17:33:03Z")

</div>

Thank you both so much for clarifying that distinction in such a clear and understandable way. I don’t think I would have pick up on it otherwise. I just marked the first answer as there is currently no way to mark multiple solutions.
