vcat([], [1 2]) # OK
vcat([], [1 "2"]) # Not OK: ERROR: ArgumentError: number of columns of each array must match (got (1, 2))
[[];[1 2]] # OK
[[];[1 "2"]] # Not OK: ERROR: ArgumentError: number of columns of each array must match (got (1, 2))
cat([], cat([], [1 2]; dims=1)) # OK
cat([], cat([], [1 "2"]; dims=1)) # OK

help?> vcat
...
vcat(A...)
Concatenate arrays or numbers vertically. Equivalent to cat(A...; dims=1), and to the syntax [a; b; c].
...

It’s not accurate to say vcat(A...) is equivalent to cat(A...; dims=1).

julia> vcat([], [1 2])
ERROR: DimensionMismatch: number of columns of each array must match (got (1, 2))

and

julia> [[];[1 2]]
ERROR: DimensionMismatch: number of columns of each array must match (got (1, 2))

How do you keep finding these things? cating empty untyped arrays [] to other stuff seems like a right code smell to me, maybe you should think about changing your approach?

Thanks. Maybe it is due to Julia version as the post above. Sorry… I was just looking for an approach to recording some process results in a loop. May I ask for some good advice on the following code?

rec = []
for i = 1:10
rec = cat(rec, rand(3)'; dims=1)
end
rec

julia> A = [[], [1 "2"]]
2-element Vector{Array{Any}}:
[]
[1 "2"]
julia> cat(A...; dims=1)
1×2 Matrix{Any}:
1 "2"
julia> vcat(A...)
ERROR: DimensionMismatch: number of columns of each array must match (got (1, 2))
Stacktrace:
⋮ internal @ Base
[3] vcat(::Vector{Any}, ::Matrix{Any})
@ Base ./abstractarray.jl:1691

I’m erroring on vcat([], [1 2]) on v1.10.2, what version is it not erroring on? Also unlike vcat and [[]; [1 2]], cat([], [1 2]; dims=1) seems to ignore [] and does not error. cat([1], [1 2]; dims=1) does throw DimensionMismatch.

I can replicate [[], [1,2]], vcat([], [1 2]). and cat([], [1,2]; dims=1) not throwing an error on both v1.9.0 and v1.9.4. [[1]; [1 2]], vcat([1], [1 2]), and cat([1], [1 2]; dims=1) throws an error on both versions. I don’t know a way to automatically test a call across all versions so I won’t do that.

This discrepancy between 1.9 and 1.10 should be an issue if it wasn’t already. Presumably someone had changed vcat and [A...] to not ignore [] anymore. Good catch.

Hi, everyone! I am still wondering if there exists more convenient method if I want to construct a matrix row by row from an empty array in a for loop, for example:

# This seems convenient except I have to define the first (two) row outside the loop:
A = rand(2,3)
for i = 1:9
A = [A; rand(2,3)]
end
# This is desired (isn't it?) but it doesn't work for all.
A = []
for i = 1:10
A = [A; rand(2,3)]
end

tmpA = Float64[]
for i = 1:10
append!(tmpA, vec(rand(2,3)))
end
A = reshape(tmpA, :, 3)

This method relegates the memory allocation to the Vector (or Memory in 1.11) code. The data undergoes less copying and should therefore be more efficient. Admittedly, it isn’t the most natural way to express the desired output.

reduce(vcat, A) is more efficient than splatting for a variable length container, especially if there are lots of rows.

You could do e.g. A = zeros(0,3) instead of A = [] to start with an empty A that has the correct number of columns (and the correct type).

However, this approach is pretty inefficient because it copies to a new array on every loop iteration — in fact, if you think about it, you should deduce that the cost grows with the square of the number of rows.

If you can compute the number of rows in advance, it’s better to pre-allocate the whole matrix A and then fill it in as desired, e.g.

N = 10
A = Matrix{Float64}(undef, 2N, 3) # pre-allocate
for i = 1:N
A[2i-1:2i, :] = rand(2,3)
# or better yet work in-place: @views rand!(A[2i-1:2i, :])
end