# How not to concatenate in hvcat

Is there a way one can use the `[...; ...]` syntax which lowers to `hvcat` without concatenating the arguments? Ie as a plain vanilla matrix constructor.

Eg

``````julia> [[1] [2];
[3] [4]]
2×2 Matrix{Int64}:
1  2
3  4
``````

concatenates, I want something equivalent to

``````julia> reshape([[1], [3], [2], [4]], :, 2)
2×2 Matrix{Vector{Int64}}:
[1]  [2]
[3]  [4]
``````

This works:

``````julia> [[[1]] [[2]];
[[3]] [[4]]]
2×2 Matrix{Vector{Int64}}:
[1]  [2]
[3]  [4]
``````

but, aargh.

1 Like

No, the lowering functions all copy elementwise from `AbstractArray` inputs.

``````julia> vcat.([1 3; 2 4])
2×2 Matrix{Vector{Int64}}:
[1]  [3]
[2]  [4]
``````

Downside is that it isn’t visually as obvious as `[[1] [2]; [3] [4]]` would be (if it worked), so probably needs a comment alongside it to explain what it’s doing.

I think you misunderstood the question; the point is not create the matrix in the MWE, but to construct a matrix using the `[ ; ]` syntax without concatenation, eg generally

``````[a b; c d]
``````

where `a::Union{AbstractVector,AbstractMatrix}` etc.

The simplest solution may be a wrapper type, eg along the lines of

``````"""
A wrapper type that should be used on the element of a `hvcat` (`[...; ...]`) call to
prevent concatenation of the arguments.
"""
struct NoCat{T}
x::T
end

function Base.hvcat(rows::Tuple{Vararg{Int}}, x1::NoCat, xR...)
nrow = length(rows)
ncol = rows[1]
@assert allequal(rows)
xs = promote(x1.x, xR...)
T = typeof(xs[1])
m = Matrix{T}(undef, nrow, ncol)
j = 1
for row in 1:nrow
for col in 1:ncol
m[row, col] = xs[j]
j += 1
end
end
m
end
``````

which works like

``````julia> [NoCat([1]) [2];
[3] [4]]
2×2 Matrix{Vector{Int64}}:
[1]  [2]
[3]  [4]
``````
1 Like

hm, unfortunately I think the current behavior is highly consistent:

``````julia> [1 2]
1×2 Matrix{Int64}:
1  2

julia> [[1] [2]]
1×2 Matrix{Int64}:
1  2

julia> [1, 2]
2-element Vector{Int64}:
1
2

julia> [[1]; [2]]
2-element Vector{Int64}:
1
2
``````

I agree with this, but I was just looking for a syntax that makes a matrix using the same visual arrangement without concatenating the elements. Julia does not have (built-in) syntax for a matrix constructor that does nothing else (cf the `[]` syntax for vectors). Fortunately it can easily be added.

2 Likes

I think it’d be a bit cleaner to instead abuse `typed_hvcat` like what StaticArrays.jl does:

``````struct var"typeof(NoCat)" end
const NoCat = var"typeof(NoCat)"()
Base.show(io::IO, ::var"typeof(NoCat)") = print(io, "NoCat")

function Base.typed_hvcat(::var"typeof(NoCat)", rows::Tuple{Vararg{Int}}, _xs...)
nrow = length(rows)
ncol = rows[1]
@assert allequal(rows)
xs = promote(_xs...)
T = typeof(xs[1])
m = Matrix{T}(undef, nrow, ncol)
j = 1
for row in 1:nrow
for col in 1:ncol
m[row, col] = xs[j]
j += 1
end
end
m
end
``````

and then

``````julia> NoCat[[1] [2]
[3] [4]]
2×2 Matrix{Vector{Int64}}:
[1]  [2]
[3]  [4]

``````
2 Likes

I absolutely agree, but AFAICT it is not part of the exposed API. Perhaps that should be fixed — I could not find an open issue I opened an issue:

1 Like