Since v0.5 comprehensions are shape-preserving (0.5-style comprehensions by JeffBezanson · Pull Request #16622 · JuliaLang/julia · GitHub ), so
m = [x for x in [1 2; 3 4]]
results in a matrix.
How should one, using a comprehension, create a vector instead? Something that better reflects a traditional for
loop:
v = Int[]
for x in [1 2; 3 4]
push!(v, x)
end
Preferably in an efficient way, with no temporaries .
m = [x for x in vec([1 2; 3 4])]
? vec
just uses a view and does’t copy.
It doesn’t seem so:
julia> typeof(vec([1 2; 3 4]))
Array{Int64,1}
That’s not testing anything. Arrays are views too.
julia> const v = [1 2;3 4]
2×2 Array{Int64,2}:
1 2
3 4
julia> @time vec(v)
0.000001 seconds (6 allocations: 240 bytes)
4-element Array{Int64,1}:
1
3
2
4
julia> const w = [1 2 3 4 5 6;3 4 7 7 8 9]
2×6 Array{Int64,2}:
1 2 3 4 5 6
3 4 7 7 8 9
julia> @time vec(w)
0.000002 seconds (6 allocations: 240 bytes)
12-element Array{Int64,1}:
1
3
2
4
3
7
4
7
5
8
6
9
julia> z = vec(w)
12-element Array{Int64,1}:
1
3
2
4
3
7
4
7
5
8
6
9
julia> z[1] = 10
10
julia> w
2×6 Array{Int64,2}:
10 2 3 4 5 6
3 4 7 7 8 9
No allocations, just the allocation of the view which is constant 240 bytes. The array just tells it how to index. Once Tim Holy explained that, the magic went away.
view, julia
Wow! That is something completely new to me! And, at a first sight, this kind of hidden aliasing seems a little bit too dangerous…
Thanks @ChrisRackauckas .
By the way, besides that comment by @tim.holy , is there any documentation on this?
vec
really doesn’t copy:
julia> A = [1 2; 3 4]
2×2 Array{Int64,2}:
1 2
3 4
julia> v = vec(A)
4-element Array{Int64,1}:
1
3
2
4
julia> A[1,1] = 11
11
julia> v
4-element Array{Int64,1}:
11
3
2
4