The index seems to be one-based or otherwise depending on whether I explicitly specify the lower and upper bounds or leave it implicit. Why is this the case?
julia> a=zeros(-1:1);
julia> b=view(a,-1:1); axes(b)
(Base.OneTo(3),)
julia> b=view(a,:); axes(b)
(Base.IdentityUnitRange(-1:1),)
julia> @which view(a,:)
view(A::AbstractArray, I::Vararg{Any,N}) where N in Base at subarray.jl:153
julia> @which view(a,-1:1)
view(A::AbstractArray, I::Vararg{Any,N}) where N in Base at subarray.jl:153
I would have expected the behavior to be identical. Why is there a difference? Is there a way to retain the index information in the view while specifying the bounds?
Indexing in Julia followsâ the following rule: if b = a[idx] for some vector index idx, then b[j] = a[idx[j]]. Since -1:1 has axes of Base.OneTo(3), b has the same indexes. This is How It Should Be.
But you can do the following:
julia> using OffsetArrays
julia> a=zeros(-1:1);
julia> b = a[Base.IdentityUnitRange(-1:1)];
julia> axes(b)
(Base.IdentityUnitRange(-1:1),)
julia> axes(a)
(Base.IdentityUnitRange(-1:1),)
What was the reasoning behind this decision? Is there a thread to read about it in this forum?
A slice of an OffsetArray loses the offsets, is quite strange (not intuitive). Those who know the b[j] == a[idx[j]] rule can deduce the How It Should Be, but you need to invoke the rule because the result is not intuitive. Those who donât know the rule have no clue.
So, I guess there needs to be the clear discussion of this behavior in the official documentation of OffsetArrays.
Also, using Base.IdentityUnitRange() is rather bulky. I wish there were a function, letâs call it slice(), to do that: bb = slice(a, -1:1) that preserves the indexing.
That could be an addition to OffsetArrays, I think it is as simple as:
julia> x = OffsetArray(1:10, -2)
1:10 with indices -1:8
julia> slice(x, range) = OffsetArray(x[range], range)
slice (generic function with 1 method)
julia> y = slice(x, 2:4)
4:6 with indices 2:4
julia> y
4:6 with indices 2:4
This only works with ranges. I had proposed this some years back, but it wasnât accepted at the time. Iâm not sure this is needed in the package, frankly, given that the composition works well. One may define this easily for their own use case.
b = a[idx] for some vector index idx, then b[j] = a[idx[j]]
Thatâs how regular array indexing works, pre OffsetArrays: if I take b = a[[3, 5, 11]], then b[1] = a[3], right? The reason is that [3, 5, 11] has indices of its own, and they are 1:3. Thus the indices of b are 1:3, i.e., the indices of the index vector become the indices of the result.
So if you want to make arrays-with-offset indices compatible with the overall AbstractArray interface, they have to follow the same rule.
What to do when you donât know the dimensionality of the OffsetArray, when you have â:â, and when one of your index ârangeâ is actually a scalar (matrix[:,1] is a 1D vector and so OffsetArray(matrix[irange,1], irange, 1) doesnât work).
So far, my code remains as tedious as the above example.
Does that mean that a lot of existing code which deals with AbstractArray already relies on the b[j] == a[idx[j]] rule? in such a way that if OffsetArrays didnât obey the rule, significant existing library code would stop working correctly with them?
Thanks, but I did understand that. I wasnât asking how the rule makes sense for 1-base arrays. It does makes sense for 1-base arrays. My point is that the rule leads to the unintuitive indexing behavior for OffsetArrays.
All in all, I guess that we should always use IdentityUnitRange with OffsetArrays. We donât do so only because we donât have a convenient syntax to create an IdentityUnitRange.
Would you care to elaborate on this? I just want to do the âcompositionâ.
Iâd appreciate it if you could show how to define such view function for my cases above? Specifically, how does one define an offset_view function that can handle
bb = offset_view(a, :, 2:3, 4)
This is my real situation. Since I haveât been able to write such a convenience function myself, my current code is bulky each time I need to take a slice of a multi-dimensional OffestArray.
Thanks! But your code indicates that such a function should be provided by the OffestArrays package because your code is too esoteric for an ordinary user to come up with.
So, I disagree with your reasoning that such a function isnât a useful part of the package because the user can easily write it.
Iâm sure that I will not be able to write such a function âDepending on [my] use caseâ.
I mean, itâs just a very different meaning of a view (and indexing in general).
The âconsistentâ behavior would mean that A[2:3] should return an offset array with indices 2:3, regardless of the type or indices of A. Thatâs just a different sort of indexing behavior than what Julia has standardized on.