From this comment, I learned that for i = eachindex(v) is preferred to for i = 1:length(v) when iterating over v::AbstractVector, because AbstractVector may not support 1-based indexing (e.g., OffsecArrays.jl).
eachindex(v) is acceptable when we want to iterate over the entire length of v. However, sometimes we want to iterate over a portion of v. For example, to calculate the gap between adjacent entries, we would want to do something like
for i = 1:length(v)-1
println(v[i+1] - v[i])
end
In this case we cannot use eachindex(v). Is there a syntax that we can use in such a case?
(Calculating the gap between adjacent entries is what diff(v) does, and diff(v) calls Base.require_one_based_indexing(v), which suggests that there may not be a simple way of handling this issue.)
Technically, the result of axes(A) where typeof(A) <: AbstractArray must be a tuple of AbstractUnitRange{<:Integer} according to the AbstractArray interface: Interfaces · The Julia Language. The step should be 1.
The problem is that we do not have a good way of enforcing this.
Often, the simplest solution might be to use OffsetArrays.no_offset_view, which will return a 1-based view that will (for mutable arrays) share memory with the parent array. So
v1 = OffsetArrays.no_offset_view(v)
for i = 1:length(v1)-1 # works now
println(v1[i+1] - v1[i])
end
This might lead to code that’s simpler to understand.