# Array step index

**URL:** <https://discourse.julialang.org/t/array-step-index/62920>\
**Category:** General Usage\
**Created:** [June 14, 2021, 10:59pm UTC](https://discourse.julialang.org/t/array-step-index/62920 "2021-06-14T22:59:40Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [June 14, 2021, 10:59pm UTC](https://discourse.julialang.org/t/array-step-index/62920/1 "2021-06-14T22:59:40Z")

</div>

There are arrays whose [first index isn’t 1](https://juliaarrays.github.io/OffsetArrays.jl/dev/). If I want the next value after the first index, is it always `x[begin+1]`, or is there a generalization like `x[begin+step]`?

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [June 14, 2021, 11:42pm UTC](https://discourse.julialang.org/t/array-step-index/62920/2 "2021-06-14T23:42:30Z")

</div>

For `AbstractArray`, almost all generic code is written assuming that the array step is 1. In theory, there’s nothing stopping someone from making an array with a different step, but in practice it might as well not be an `<:AbstractArray` because it won’t work with anything.

However, for `String`s, you often have a situation where the indices are non-uniform and have weird steps, so there’s a `nextind` function that does what you want.

```julia
julia> for x in ("αβγ", (:α, :β, :γ), [:α, :β, :γ])
           @show x
           @show nextind(x, firstindex(x))
           @show x[nextind(x, begin)]
           println()
       end
x = "αβγ"
nextind(x, firstindex(x)) = 3
x[nextind(x, begin)] = 'β'

x = (:α, :β, :γ)
nextind(x, firstindex(x)) = 2
x[nextind(x, begin)] = :β

x = [:α, :β, :γ]
nextind(x, firstindex(x)) = 2
x[nextind(x, begin)] = :β

```

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [June 14, 2021, 11:51pm UTC](https://discourse.julialang.org/t/array-step-index/62920/3 "2021-06-14T23:51:00Z")

</div>

I think, that, unfortunately, the only safe way to iterate over non-unitary steps are:

1. Using `keys` to have access to the whole list of indexes.
2. Calling `iterate` by hand, which does not actually gives you the indexes, but allows you to go step-by-step.

I disagree a little with Mason, even if he is probably more informed than me, because I think there are a lot of algorithms that just iterate over `AbstractArray` or use other functions never relying directly on incrementing steps one by one, but you will probably hit one or another function that makes this assumption.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [June 15, 2021, 1:56am UTC](https://discourse.julialang.org/t/array-step-index/62920/4 "2021-06-15T01:56:49Z")

</div>

> [@Henrique\_Becker](#):
>
> I think, that, unfortunately, the only safe way to iterate over non-unitary steps are:
> 
> 1. Using `keys` to have access to the whole list of indexes.
> 2. Calling `iterate` by hand, which does not actually gives you the indexes, but allows you to go step-by-step.

What’s wrong with `nextind` (assuming it’s been implemented for the collection in question)?

> [@Henrique\_Becker](#):
>
> I think there are a lot of algorithms that just iterate over `AbstractArray` or use other functions never relying directly on incrementing steps one by one, but you will probably hit one or another function that makes this assumption.

Yeah, this depends a lot on what functions you’re using. There are definitely lots of functions which will be okay, but I think using an `AbstractArray` with non-unit steps is just generally going to be a minefield when faced with generic function implementations.

The worst part is that you won’t even get method-errors when you end up hitting a function that assumes unit steps, instead you’ll just get a silently incorrect program, and a lot of `AbstractArray` code in `Base` and `LinearAlgebra` is somewhat deeply nested, so making sure that a function makes correct assumptions about step sizes will involve a large amount of detective-work, looking at nested call chains and each function in that chain to make sure it doesn’t index by steps of 1. But even if `Base` and `LinearAlgebra` were safe in this regard, many many packages won’t be.

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [June 15, 2021, 2:12am UTC](https://discourse.julialang.org/t/array-step-index/62920/5 "2021-06-15T02:12:05Z")

</div>

> [@Mason](#):
>
> What’s wrong with `nextind` (assuming it’s been implemented for the collection in question)?

For what I understand, `nextind` is not part of any `AbstractArray` or general collection interfaces but a function to be used with `String`s. In other words, `nextind` is not a generic function that obtains the next index but by chance was only implemented for `String`, `nextind` is a `Base` function without any meaning outside of the scope of the `String` type. Re-using the name seems to be an inadequate decision, it is punning.

> [@Mason](#):
>
> There are definitely lots of functions which will be okay, but I think using an `AbstractArray` with non-unit steps is just generally going to be a minefield when faced with generic function implementations.

I agree. In my package’s code I tried to not suppose the step size, but in some cases it is hard to even not assume one-based indexing.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [June 15, 2021, 3:08am UTC](https://discourse.julialang.org/t/array-step-index/62920/6 "2021-06-15T03:08:25Z")

</div>

Hm, we’ll someone definitely took the time to implement `nextind` for abstract arrays and tuples:

```julia
julia> methods(nextind)
# 9 methods for generic function "nextind":
[1] nextind(s::SubString{String}, i::Int64) in Base at strings/substring.jl:96
[2] nextind(s::String, i::Int64) in Base at strings/string.jl:137
[3] nextind(t::Tuple, i::Integer) in Base at tuple.jl:67
[4] nextind(::AbstractArray, i::Integer) in Base at abstractarray.jl:150
[5] nextind(s::AbstractString, i::Int64) in Base at strings/basic.jl:537
[6] nextind(s::AbstractString, i::Int64, n::Int64) in Base at strings/basic.jl:539
[7] nextind(s::AbstractString, i::Integer) in Base at strings/basic.jl:536
[8] nextind(s::AbstractString, i::Integer, n::Integer) in Base at strings/basic.jl:535
[9] nextind(a::AbstractArray{var"#s828",N} where var"#s828", i::CartesianIndex{N}) where N in Base.IteratorsMD at multidimensional.jl:149

```

Though only the `String` method is actually documented. Perhaps the other methods could be documented as well, and we could make it part of the `AbstractArray` interface.

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [June 15, 2021, 3:29am UTC](https://discourse.julialang.org/t/array-step-index/62920/7 "2021-06-15T03:29:11Z")

</div>

Nice, I did not know someone had implemented this. However, if it is not in the `Base` documentation then it is not part of the public API. I would not suggest its use, for now it is just an implementation detail. I can open a PR tomorrow to check if this is intended to be public API.

---

<div class="post-metadata">

**Author:** ![cjdoris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cjdoris/32/213133_2.png) [@cjdoris](https://discourse.julialang.org/u/cjdoris)\
**Post date:** [June 15, 2021, 8:57pm UTC](https://discourse.julialang.org/t/array-step-index/62920/8 "2021-06-15T20:57:00Z")

</div>

According to [Interfaces · The Julia Language](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-array) the axes of an array are always `AbstractUnitRange{<:Integer}`, so yes the step is always 1.

---

<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:** [June 15, 2021, 9:59pm UTC](https://discourse.julialang.org/t/array-step-index/62920/9 "2021-06-15T21:59:18Z")

</div>

If you want a non-unit step, just use views to re-index into your contiguous (dense) 1-step array with a `StepRange` like `@view v[begin:2:end]` or `@view A[begin:2:end, :]`. The resulting object will have ~half as many values and will still act like a normal 1-step array with an axis like `1:length(v)÷2`… but will seamlessly interface with BLAS as a strided array with non-unit steps.

In other words, while Julia’s arrays always _expose_ 1-step (unit range) axes, their _storage_ can be whatever it needs to be — and views can effortlessly and efficiently do this transformation.
