Could you explain what are views?


#1

Hello.

Could you explain to a new user what are @view, @views, and other alternatives, please?
What is something equivalent on base R or data.table?

For example if I do:

A = [1 2; 3 4]
A[:,:]

I get:

2×2 Array{Int64,2}:
1 2
3 4

The same if I do:

@view A[:,:]
2×2 view(::Array{Int64,2}, :, :slight_smile: with eltype Int64:
1 2
3 4

or if I do:

@views A[:, :]
2×2 view(::Array{Int64,2}, :, :slight_smile: with eltype Int64:
1 2
3 4

I get the same result. I don’t understand the difference.
When do I need to use views?

The documentation provides this explanation, but anyway I don’t understand the meaning of view:

view: Like getindex but returns a view into the parent array  `A`  with the
given indices. 
getindex: retrieves the value(s) stored at the given key or index within a
 collection.
@views: Convert every array-slicing operation in the given expression 
@view: Creates a  SubArray  from an indexing expression.

#2

Try and modify the result, and you’ll see the difference:

julia> A = [1 2; 3 4];
julia> B = A[:,:];   # This is actually a copy of A
julia> B[1,1]=0;
julia> A
2×2 Array{Int64,2}:
 1  2
 3  4

julia> B
2×2 Array{Int64,2}:
 0  2
 3  4

But:

julia> B = @view A[:,:];   # B is a view of A
julia> B[1,1]=0;
julia> A   # Ooops!
2×2 Array{Int64,2}:
 0  2
 3  4

julia> B
2×2 view(::Array{Int64,2}, :, :) with eltype Int64:
 0  2
 3  4

In this particular case, it’s the same as B = A, so @view does not seem very useful. It makes more sense when you look at some slice, e.g. B = @view A[1,:] (a view of the first row).

That’s useful if you want to make some calculations based on the values of particular rows, columns or blocks of a matrix, without having to make a copy of that portion of the array (which takes more memory and time). Just take care with the changes, as in the example!

@view only applies to the slice next to the macro name; @views makes views to all the slices right to it.


#3

In short, a “view” is a data structure that acts like an array (it is a subtype of AbstractArray in Julia), but the underlying data is actually part of another array.

For example, if x is an array and v = @view x[1:10], then v acts like a 10-element array, but its data is actually accessing the first 10 elements of x. Writing to a view, e.g. v[3] = 2, writes directly to the underlying array x (in this case modifying x[3]).

Slicing operations like x[1:10] create a copy by default in Julia. @view x[1:10] changes it to make a view. The @views macro can be used on a whole block of code (e.g. @views function foo() .... end or @views begin ... end to change all the slicing operations in that block to use views.

Sometimes making a copy of the data is faster and sometimes using a view is faster, as described in the manual.

The “views” terminology is pretty standard; e.g. similar terminology is used in NumPy (which defaults to views for slices) and Boost for C++.

A pull request to improve the Julia documentation would be welcome.