Even if claiming ordinal might be okayish, Iām still finding it difficult to imagine how the interface of literally every ordered collection could be respecified in a satisfactory way that wouldnāt also be considered hugely breaking, by any agreeable notion of what ābreakingā means. Maybe Iām just unimaginative, but Iām having trouble here.
Part of me is also beginning to suspect that the notion of ordinal indices for ordered collections is somehow related to the notion of tokens for unordered collections.
The definition of a breaking change in software is a bit weirdāit means something that breaks a promise you made in an earlier version of software, not something that could conceivably break a piece of code. As far as Iām aware, the Julia devs havenāt promised never to add new identifiers to the language.
Namespacing should also keep this from breaking anything. If you define th = 1 in a function, the local variable th refers to something different from the th object.
Per usual, this was an ignorant comment. A brief look into how itās currently done (since I hadnāt looked into it until now):
Base has the function Base.to_indices for arrays, which OrdinalIndexing.jl overloads to convert ordinal indices into cardinal indices. Example with the simpler Base.to_index:
This is what enables it to work without having to overload all the Base.getindex methods for AbstractArray types (and deal with all the dispatch ambiguities that would pose).
For the AbstractRange type, OrdinalIndexing.jl overloads the Base.getindex and Base.view methods as necessary.
So if we want ordinal indices to work with other ordered collections, this demonstrates two paths:
specify that Base.to_indices should become part of their interface, or
specify appropriate Base.getindex and Base.view methods for ordinal indices
Neither of these seems that breaking, although it seems like #1 is better to avoid dispatch ambiguitiesā¦
julia> A = OffsetArray(reshape(1:4, 2, 2), 3:4, 5:6)
2Ć2 OffsetArray(reshape(::UnitRange{Int64}, 2, 2), 3:4, 5:6) with eltype Int64 with indices 3:4Ć5:6:
1 3
2 4
julia> reshape(A, size(A)) # same array, but with 1-based indices
2Ć2 reshape(::UnitRange{Int64}, 2, 2) with eltype Int64:
1 3
2 4
This doesnāt always work, though, and OffsetArrays.no_offset_view is guaranteed to produce 1-based views.
Indeed OffsetArrays.no_offset_view produces exactly this idea, but that doesnāt solve the issue that gets some people to ponder whether OffsetArrays.jl is a poison pill. Namely, we would ideally have something inBasewhich offers assurance that 1-based indices will work on an arbitraryAbstractArray.
This is exactly what OrdinalIndices.jl provides by offering an ordinal index type. Iām toying with the alternative approach of using an ordinally indexed view, that ordinal(A) will be a 1-based-indexed view of A.
Apparently this idea was already pondered here but deserves more exploration imo. It would be really easy to add it to the AbstractArray specification, and the fallback method is the easiest thing in the world.
ordinal(A::AbstractArray) = A
this would place the burden on OffsetArrays to add the method: