3 ms·
This is not true. For example, the issue regarding custom index ranges causing silent data corruption (6 examples) could be fixed with static types. Look how m
by grumpyprole 4y ago
This is not true. For example, the issue regarding custom index ranges causing silent data corruption (6 examples) could be fixed with static types.
Look how many of the other bug reports contain the phrase "does not check for" or refer to specific primitive types.
- adgjlsfhk1 4y agoit is only fixed with static typing and no generics (i.e. C/Fortran). If you have a generic array supertype, a statically typed language would let you write exactly the same bug.
- grumpyprole 4y agoIf one has a different type or trait for unusual and normal range indices, then the signature for the procedure that assumes indexing from 1 can be written to disallow other starting indices.
- DNF2 4y agoHow would static types help with that? Whether your indexing range starts with zero or one or something else isn't necessarily encoded in the type domain. `1:length(A)` is just a range of `Int`s.
- grumpyprole 4y agoWhy not encode the starting offset into the type domain? Or at least distinguish between normal and unusual. Then the function signature can restrict to 1-offset arrays if that is what it assumes internally.
- DNF2 4y agoThat means disallowing indexing with integers, I presume? Since an integer can take the values 0 or 1 equally. And what about the other end of the array. Must every index be restricted by type to be located in the acceptable range?
- markkitti 4y agoIf the function signature said `Array` rather than `AbstractArray`, then this code would have been fine. `Array` indexing starts at `1`. ``` julia> function f(A::Array) println(A[1:length(A)]) end f (generic function with 1 method) julia> f([1,2,3,4]) [1, 2, 3, 4] julia> f(OffsetArray(1:10, -1)) ERROR: MethodError: no method matching f(::OffsetVector{Int64, UnitRange{Int64}}) ``` You could prevent this problem using Julia's type system. The `AbstractArray` might have been too broad. Based on the chronology of the code that might not have been apparent. See other threads for details. Another way would be to treat `firstindex` as a trait and dispatch on that. ``` julia> f(A::AbstractArray) = f(A, Val(firstindex(A))) f (generic function with 1 method) julia> f(A::AbstractArray, firstindex::Val{1}) = println(A[1:length(A)]) f (generic function with 2 methods) julia> f(A::AbstractArray, firstindex::Val{T}) where T = error("Indexing for array does not start at 1") f (generic function with 3 methods) julia> f(A::AbstractArray, firstindex::Val{0}) = println("So you like 0-based indexing?") f (generic function with 4 methods) julia> f([1,2,3,4]) [1, 2, 3, 4] julia> using OffsetArrays julia> f(OffsetArray(1:10, 1)) ERROR: Indexing for array does not start at 1 Stacktrace: [1] error(s::String) @ Base .\error.jl:33 [2] f(A::OffsetVector{Int64, UnitRange{Int64}}, #unused#::Val{2}) @ Main .\REPL[5]:1 [3] f(A::OffsetVector{Int64, UnitRange{Int64}}) @ Main .\REPL[3]:1 [4] top-level scope @ REPL[9]:1 julia> f(OffsetArray(1:10, -1)) So you like 0-based indexing? ```
- DNF2 4y agoThe starting offset is encoded in the type domain, btw, and accessible with the `firstindex` function. But you will still want to calculate indices at runtime, and then out-of-bounds errors will have to be caught at runtime anyway.