I think that depends on how much the library wants to introduce a new syntax. For that specific operation a function is perfectly fine.
As a side note, the thing that makes Julia special relative to some other high-level languages, is that you can sometimes solve a problem just writing down your own function, which can be very efficient, and that may be quicker than even discovering if there is something ready to use. In this case, for example, you can use:
julia> function stack(M)
n, m = length(M[begin]), length(M)
all(length(v) == n for v in M) || error("all vecs must be of same length")
return [ M[j][i] for i in 1:n, j in 1:m ]
end
stack (generic function with 1 method)
julia> stack([[1,2],[3,4]])
2×2 Matrix{Int64}:
1 3
2 4
You can do, without new implementations:
julia> reduce(hcat, M)
2×2 Matrix{Int64}:
1 3
2 4
(and, - and this is good! - the above function and this option are equally performant, just by adding an @inbounds
to the M[j][i]
in the stack
function):
julia> M = [ rand(10) for _ in 1:10 ];
julia> @btime reduce($hcat, $M);
104.482 ns (1 allocation: 896 bytes)
julia> function stack(M)
n, m = length(M[begin]), length(M)
all(length(v) == n for v in M) || error("all vecs must be of same length")
return [ @inbounds(M[j][i]) for i in 1:n, j in 1:m ]
end
stack (generic function with 1 method)
julia> @btime reduce($hcat, $M);
103.343 ns (1 allocation: 896 bytes)
edit: For why you can’t do Matrix([[1,2],[3,4]])
, my guess is that because this is not a trivial operation, it is not simply a data reintpretation. The input is a vector of vectors, which is a vector of pointers that point to the input vectors. The output has a packed memory layout, thus a completely different object, that has to be created somewhere else in the memory. Performance-wise one should try to avoid this type of conversion, which on the other side is very common in workflows in other languages, and perhaps useful in data-mangling in general (not mentioning the confusion caused by the fact that the vector-of-vectors notation may be just a matrix in numpy). Having to use reduce(hcat, v)
is not bad, from an didactic point of view, clearly indicating what one is doing there.