Undoing a view

view(b, ixs) creates a view that references the original storage a, rather than the intermediate view b. I am interested in getting the argument b back out of c, undoing the second slice.

Is there something like either

  • a “hard view” b, views of which remember they came from b?
  • a “shallow view” @shallowview that remembers it came from b?
julia> a = [10,20,30,40]
4-element Vector{Int64}:
 10
 20
 30
 40

julia> b = @view a[2:end]
3-element view(::Vector{Int64}, 2:4) with eltype Int64:
 20
 30
 40

julia> c = @view b[2:end]
2-element view(::Vector{Int64}, 3:4) with eltype Int64:
 30
 40

julia> dump(c)
SubArray{Int64, 1, Vector{Int64}, Tuple{UnitRange{Int64}}, true}
  parent: Array{Int64}((4,)) [10, 20, 30, 40]
  indices: Tuple{UnitRange{Int64}}
    1: UnitRange{Int64}
      start: Int64 3
      stop: Int64 4
  offset1: Int64 2
  stride1: Int64 1
julia> parent(c)
4-element Vector{Int64}:
 10
 20
 30
 40

EDIT: Sorry, think I misunderstood what you wanted…

Not builtin, no. The builtin subarray does all sorts of magic with the indices (and even the parent) such that you cannot reliably ask these questions of the builtin views.

But this could definitely be a package. This kind of “index-forward” or “process-oriented” mental model where the exact parent & indices matter just as much (or more) than the data they select is a very different view (pun intended) than the builtin takes.

1 Like

You can make this by calling the SubArray constructor explicitly, rather than via view:

julia> c2 = SubArray(b, (2:lastindex(b),))
2-element view(view(::Vector{Int64}, 2:4), 2:3) with eltype Int64:
 30
 40

julia> dump(c2)
SubArray{Int64, 1, SubArray{Int64, 1, Vector{Int64}, Tuple{UnitRange{Int64}}, true}, Tuple{UnitRange{Int64}}, true}
  parent: SubArray{Int64, 1, Vector{Int64}, Tuple{UnitRange{Int64}}, true}
    parent: Array{Int64}((4,)) [10, 20, 30, 40]
    indices: Tuple{UnitRange{Int64}}
      1: UnitRange{Int64}
        start: Int64 2
        stop: Int64 4
    offset1: Int64 1
    stride1: Int64 1
  indices: Tuple{UnitRange{Int64}}
    1: UnitRange{Int64}
      start: Int64 2
      stop: Int64 3
  offset1: Int64 1
  stride1: Int64 1
3 Likes

True! I had forgotten where we had put all the indexing jiggery-pokery; it’s in view, not in the constructor. On the flip side, it doesn’t do indexing jiggery-pokery, so caller beware:

  • No bounds checks
  • No support for linear or logical indexing
  • No support for CartesianIndex or other non-integer (or non-array-of-integer) indices
3 Likes

Also the constructor is not described in the SubArray doc string, which however says that view is the intended way of constructing SubArray values. Giving the impression that the SubArray constructor may not be a stable interface.