What's behind the scenes of the view (...) function?

Since to (almost. Which not?) All the effects the following two assignments are equivalent, why, since view is faster and cheaper, is not [ ] (ie getindex) defined in the same way?

a=[1,2,3]
b=a[1:2]
b=view(a, 1:2)

If the explanation isn’t too laborious, in this simple case, I’d like to know what view() does differently than getindex() to be faster and not allocate.

You can see the difference between getindex and view when mutating an element of b:

julia> a = [1, 2, 3];

julia> b = a[1:2]
2-element Vector{Int64}:
 1
 2

julia> c = view(a, 1:2)
2-element view(::Vector{Int64}, 1:2) with eltype Int64:
 1
 2

julia> b[1] = 4
4

julia> a  # Data in a is unchanged
3-element Vector{Int64}:
 1
 2
 3

julia> c[1] = 4
4

julia> a  # Data in a has changed as well
3-element Vector{Int64}:
 4
 2
 3

Thus, getindex will take the values from the slice and copy it into a new array. In contrast, view just wraps the original array and indexes into it. Thereby, getindex is safer to use, i.e., as it cannot change the data it has been taken from, whereas view is faster as it does not need to copy.

view wraps the array in in a SubArray:

julia> A = rand(3, 4)
3×4 Matrix{Float64}:
 0.479355   0.829413  0.69798   0.614651
 0.767674   0.997691  0.378664  0.77445
 0.0120585  0.260765  0.696942  0.819525

julia> V = view(A, 1:2, :)
2×4 view(::Matrix{Float64}, 1:2, :) with eltype Float64:
 0.479355  0.829413  0.69798   0.614651
 0.767674  0.997691  0.378664  0.77445

julia> typeof(V)
SubArray{Float64, 2, Matrix{Float64}, Tuple{UnitRange{Int64}, Base.Slice{Base.OneTo{Int64}}}, false}

You can find the parent array and the indices in the SubArray fields:

julia> V.indices
(1:2, Base.Slice(Base.OneTo(4)))

julia> V.parent
3×4 Matrix{Float64}:
 0.479355   0.829413  0.69798   0.614651
 0.767674   0.997691  0.378664  0.77445
 0.0120585  0.260765  0.696942  0.819525
1 Like

Read the manual on what a view is: Arrays · The Julia Language

See also Could you explain what are views?

1 Like

I had an unclear idea that this was the main difference. This is why I tried to make tests similar to those you illustrated, but, for some mess I made, I found the same result in both cases …