# Using the iteration interface with custom indices

**URL:** <https://discourse.julialang.org/t/using-the-iteration-interface-with-custom-indices/46600>\
**Category:** New to Julia\
**Tags:** iterative\
**Created:** [September 14, 2020, 6:38pm UTC](https://discourse.julialang.org/t/using-the-iteration-interface-with-custom-indices/46600 "2020-09-14T18:38:56Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![jlchan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlchan/32/10958_2.png) [@jlchan](https://discourse.julialang.org/u/jlchan)\
**Post date:** [September 14, 2020, 6:38pm UTC](https://discourse.julialang.org/t/using-the-iteration-interface-with-custom-indices/46600/1 "2020-09-14T18:38:56Z")

</div>

I’m a bit confused on how to use iteration utilities with a custom index set. I tried a MWE (just reproducing a for loop) as follows:

```julia
struct CustomIndex
    i::Int
end

struct CustomIndexSet
    n::Int
end

Base.iterate(I::CustomIndexSet) = I,CustomIndex(1)
function Base.iterate(I::CustomIndexSet,i::CustomIndex)
    if i.i+1 <= I.n
        return I,CustomIndex(i.i+1)
    else
        return nothing
    end
end

```

I want `for i in CustomIndexSet(4)` to give `1,2,3,4`, but instead I get

```julia
julia> for i in CustomIndexSet(4)
       @show i
       end
i = CustomIndexSet(4)
i = CustomIndexSet(4)
i = CustomIndexSet(4)
i = CustomIndexSet(4)

```

What’s the right way to go about this?

---

<div class="post-metadata">

**Author:** ![jlchan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlchan/32/10958_2.png) [@jlchan](https://discourse.julialang.org/u/jlchan)\
**Post date:** [September 14, 2020, 6:51pm UTC](https://discourse.julialang.org/t/using-the-iteration-interface-with-custom-indices/46600/2 "2020-09-14T18:51:37Z")

</div>

I also tried just defining a iterator using just `CustomIndex` (with hardcoded stopping point)

```julia
struct CustomIndex
    i::Int
end
Base.iterate(I::CustomIndex) = CustomIndex(1),1
function Base.iterate(i::CustomIndex,state)
    if i.i+1 <= 4
        return CustomIndex(i.i+1),state+1
    else
        return nothing
    end
end

```

then `for i in CustomIndex(1)` gives an infinite loop with

```julia
i = CustomIndex(1)
i = CustomIndex(1)
...

```

However, the `iterate` function seems to work (returns `nothing` when expected).

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [September 14, 2020, 6:58pm UTC](https://discourse.julialang.org/t/using-the-iteration-interface-with-custom-indices/46600/3 "2020-09-14T18:58:17Z")

</div>

it’s because the first argument returned by `iterate` is the “value” (`i`) you will get:

```julia
julia> struct CustomIndex
           n::Int
       end

julia> Base.iterate(S::CustomIndex, state=1) = state > S.n ? nothing : (state, state+1)

julia> for i in CustomIndex(4)
              @show i
              end
i = 1
i = 2
i = 3
i = 4

```

---

<div class="post-metadata">

**Author:** ![jlchan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlchan/32/10958_2.png) [@jlchan](https://discourse.julialang.org/u/jlchan)\
**Post date:** [September 14, 2020, 7:00pm UTC](https://discourse.julialang.org/t/using-the-iteration-interface-with-custom-indices/46600/4 "2020-09-14T19:00:54Z")

</div>

This solves the MWE, but I want `state` to be a `CustomIndex`. Does this mean that if `state` is a `CustomIndex`, then it needs to also carry information about the range?

In my actual problem, I’m trying to increment `state` as a custom-typed multi-index.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [September 14, 2020, 7:05pm UTC](https://discourse.julialang.org/t/using-the-iteration-interface-with-custom-indices/46600/5 "2020-09-14T19:05:38Z")

</div>

in your first example, your `I.n` is always `4`, so no surprise there. And your custom-typed indexing was working just fine.

```julia
Base.iterate(I::CustomIndexSet, i::CustomIndex=CustomIndex(1)) = i.i, i

julia> function Base.iterate(I::CustomIndexSet,i::CustomIndex)
        i.i <= I.n && return i.i,CustomIndex(i.i+1)
        nothing
   end

julia> for i in CustomIndexSet(4)
              @show i
           end
i = 1
i = 2
i = 3
i = 4

```

---

<div class="post-metadata">

**Author:** ![jlchan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlchan/32/10958_2.png) [@jlchan](https://discourse.julialang.org/u/jlchan)\
**Post date:** [September 14, 2020, 7:12pm UTC](https://discourse.julialang.org/t/using-the-iteration-interface-with-custom-indices/46600/6 "2020-09-14T19:12:31Z")

</div>

I see that I reversed the arguments in

```julia
Base.iterate(I::CustomIndexSet) = 1,CustomIndex(1)

```

I got confused by the description in the [manual](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-iteration) of `iterate`:

> Returns either a tuple of the first item and initial state or [`nothing`](https://docs.julialang.org/en/v1/base/constants/#Core.nothing) if empty

“Item” and “state” seem interchangeable and ambiguous.

---

<div class="post-metadata">

**Author:** ![jlchan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlchan/32/10958_2.png) [@jlchan](https://discourse.julialang.org/u/jlchan)\
**Post date:** [September 14, 2020, 7:22pm UTC](https://discourse.julialang.org/t/using-the-iteration-interface-with-custom-indices/46600/7 "2020-09-14T19:22:37Z")

</div>

This doesn’t quite fix it though - I’m trying to extract the state from the iterator, e.g. something like

```julia
julia> for i in CustomIndexSet(4)
              @show i
           end
i = CustomIndex(1)
i = CustomIndex(2)
i = CustomIndex(3)
i = CustomIndex(4)

```

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [September 14, 2020, 7:24pm UTC](https://discourse.julialang.org/t/using-the-iteration-interface-with-custom-indices/46600/8 "2020-09-14T19:24:10Z")

</div>

```julia
julia> function Base.iterate(I::CustomIndexSet,i::CustomIndex)
           if i.i <= I.n
               return i,CustomIndex(i.i+1)
           else
               return nothing
           end
       end

julia> for i in CustomIndexSet(4)
              @show i
           end
i = CustomIndex(1)
i = CustomIndex(2)
i = CustomIndex(3)
i = CustomIndex(4)

```

difference on line 3

---

<div class="post-metadata">

**Author:** ![jlchan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlchan/32/10958_2.png) [@jlchan](https://discourse.julialang.org/u/jlchan)\
**Post date:** [September 14, 2020, 7:33pm UTC](https://discourse.julialang.org/t/using-the-iteration-interface-with-custom-indices/46600/11 "2020-09-14T19:33:29Z")

</div>

Thanks to @jling, here’s a MWE:

```julia
struct CustomIndex
    i::Int
end
struct CustomIndexSet
    n::Int
end
# Base.iterate(I::CustomIndexSet) = 1,CustomIndex(1)
Base.iterate(I::CustomIndexSet, i::CustomIndex=CustomIndex(1)) = i.i, i
function Base.iterate(I::CustomIndexSet,i::CustomIndex)
   if i.i <= I.n
       return i,CustomIndex(i.i+1)
   else
       return nothing
   end
end

```

which gives

```julia
julia> for i in CustomIndexSet(4)
       @show i
       end
i = CustomIndex(1)
i = CustomIndex(2)
i = CustomIndex(3)
i = CustomIndex(4)

```

---

<div class="post-metadata">

**Author:** ![jlchan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlchan/32/10958_2.png) [@jlchan](https://discourse.julialang.org/u/jlchan)\
**Post date:** [September 14, 2020, 8:03pm UTC](https://discourse.julialang.org/t/using-the-iteration-interface-with-custom-indices/46600/12 "2020-09-14T20:03:49Z")

</div>

I’m still am unclear on why these two lines return different results:

```julia
Base.iterate(I::CustomIndexSet) = 1,CustomIndex(1)
Base.iterate(I::CustomIndexSet, i::CustomIndex=CustomIndex(1)) = i.i, i

```

The first line forces a return of `CustomIndex(1)` as behavior for the first iterate

```julia
julia> for i in CustomIndexSet(4)
       @show i
       end
i = 1
i = CustomIndex(1)
i = CustomIndex(2)
i = CustomIndex(3)
i = CustomIndex(4)

```

The second one has `CustomIndex(1)` as an optional argument - but why does this remove the appearance of an extra entry in the for loop?

---

<div class="post-metadata">

**Author:** ![jlchan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlchan/32/10958_2.png) [@jlchan](https://discourse.julialang.org/u/jlchan)\
**Post date:** [September 16, 2020, 4:17pm UTC](https://discourse.julialang.org/t/using-the-iteration-interface-with-custom-indices/46600/13 "2020-09-16T16:17:09Z")

</div>

For anyone reading this thread, @mkitti clarified this on Slack for me.

I was having `Base.iterate` return current item + next state, when it should just return next item + next state (which can be the same). MWE for this is now:

```julia
struct CustomIndex
    i::Int
end
struct CustomIndexSet
    n::Int
end
Base.iterate(I::CustomIndexSet) = CustomIndex(1),CustomIndex(1)
function Base.iterate(I::CustomIndexSet,i::CustomIndex)
    if i.i < I.n
        return CustomIndex(i.i+1),CustomIndex(i.i+1)
    else
       return nothing
   end
end

```

which gives for

```julia
for i in CustomIndexSet(3)
    @show i
end

```

the desired result

```julia
for i in CustomIndexSet(3)
       @show i
       end
i = CustomIndex(1)
i = CustomIndex(2)
i = CustomIndex(3)

```
