I think Mark is thinking of julia versions pre-1.5 where any time you wrapped a mutable struct with an immutable struct, you incurred a small allocation.
I understood that ultimately the two views of each element vector of the parent vector must be allocated in a (new?) vector.
Or is it possible to make a view of the views?
PS
Instead, I wonder if the use that can be made of the two parts into which one wants to divide the vector cannot be replaced, in all necessary cases, by the use of simple index formulas
@view x1[j][1:len[j]]
or
@view x1[j][len[j]+1 : lastindex(x1[j])
or both?
In this way there is no new allocation but only the reading of the necessary data where and when it is needed.
function split(x ::Vector{Vector{Float64}}, len ::Vector{Int})
ns = eachindex(x, len)
xl = map(ns) do j
view(x[j], 1:len[j])
end
xr = map(ns) do j
view(x[j], len[j]+1:length(x[j]))
end
xl, xr
end;
this returns a Tuple of the left and right views of the arrays and doesn’t modify the input at all.
Notice that since x2 is of type Vector{Vector{Float64}}, when you do x2[j] = view(...), then there is an implicit convert(Vector{Float64}, view(...)) in order to store the view in the vector. This is what is causing you to incur so many allocations.
Yeah that’s fine, but it can be more annoying to access the views. i.e. if you want all the left views, you need ot allocate a new vector which is first.(split2(x, len))
in the form perhaps closest to the OP’s request (without allocations )
julia> @btime begin
vleft=((@view x1[j][1:len[j]]) for j in eachindex($len))
vrigth=((@view x1[j][len[j]+1:lastindex(x1[j])]) for j in eachindex($len))
end
1.500 ns (0 allocations: 0 bytes)
Base.Generator{Base.OneTo{Int64}, var"#24#26"}(var"#24#26"(), Base.OneTo(100000))