Proposal: override the error message for avector[0] with a message that specify explicitly that array indexing starts at 1 in Julia ??
I know: “If we do it for this, why not for …” but it is such a common error for people coming from C/Java/Python, that maybe it deserves a reflection (or maybe it has saready been discussed with a conclusion not to implement it, that’s fine…)
(special case 0 sounds okay, but most of the time it’s not useful because people won’t hard-code 0 over and over)
the language shouldn’t be optimized for first-time user and the goal is never to make Julia “you can use it without ever reading docs or googleing and just fix what error message says”
Without wanting to muddy the thread, these two cases’ error msgs are too similar for being so different:
julia> Int[1][0]
ERROR: BoundsError: attempt to access 1-element Vector{Int64} at index [0]
julia> Int[][0]
ERROR: BoundsError: attempt to access 0-element Vector{Int64} at index [0]
It seems like the problem is that the error reports the size of the array but given OffsetArrays etc, in order to understand bounds-checking failure you need to know the bounds, not the size, of the array.
I wonder if it’s more likely for them to know syntax 1:231 or that Julia is 1-based indexing.
In any case, we need to use firstindex() and lastindex() to generate that message in case OffsetArrays or similar is involved, but even then, some one may have a skipping-index array? (does this conflict with array interface?)
I would hope this would be a more general message than just "$(firstindex(x)):$(lastindex(x))" . Perhaps a showindices(io, x) that defaults to show(io, eachindex(x)) (perhaps with some cosmetic modification to things like Base.OneTo).
julia> OffsetArray([1,2],3)[6]
ERROR: BoundsError: attempt to access 2-element OffsetArray(::Vector{Int64}, 4:5) with eltype Int64 with indices 4:5 at index [6]
julia> OffsetArray([1 2; 3 4],5,6)[6]
ERROR: BoundsError: attempt to access 2×2 Matrix{Int64} at index [6]
julia> OffsetArray([1 2; 3 4],5,6)[7,9]
ERROR: BoundsError: attempt to access 2×2 OffsetArray(::Matrix{Int64}, 6:7, 7:8) with eltype Int64 with indices 6:7×7:8 at index [7, 9]
I still like @gustaphe’s suggestion; we could do something like that for the default message in which case OffsetArrays may not even need to customize it. That said, it can be helpful to know the size and type of the array in figuring out which one errored… but that’s kinda secondary to the most important part (the attempted index and the valid indices).
It could also be helpful to more directly talk about what is wrong when there are the wrong number of indices for a multidimensional array or which dimension is the troublesome one.
julia> x[1.25]
BoundsError: tried to access MyRealIndexedObject at index 1.25, legal indices are reals in [0.0, 1.0).
This might be overkill, but see what a bit of generality can do. Allowing some customization on this message would mean it’s more likely to be user friendly, rather than technically perfectly accurate.
What about Base.Experimental.register_error_hint? I know its experimental, but this could be readily used used to implement such hints:
Base.Experimental.register_error_hint(BoundsError) do io, ex
arrayDim(::Array{T,N}) where {T,N} = N
if ex.a isa Array && arrayDim(ex.a)>0 && 0 in ex.i
printstyled(io,"\nHint: In Julia, the standart Arrays start at 1", color=:cyan)
end
end
a=[1,2]
a[0]
BoundsError: attempt to access 2-element Vector{Int64} at index [0]
Hint: In Julia, the standart Arrays start at 1
Stacktrace:
.....
Yes it can! When a BoundsError is thrown, the errorhandler you defined for register_error_hint gets passed the thrown Exception (the argument ex in my example), and the Exception itself contains references to both the indices and the object (array) that was accessed (as ex.a for the array and ex.i for the indices, as a Tuple).