# 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> [ ;
 ]
2×2 Matrix{Int64}:
1  2
3  4
``````

concatenates, I want something equivalent to

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

This works:

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

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}}:
  
  
``````

Downside is that it isn’t visually as obvious as `[ ;  ]` 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
@assert allequal(rows)
xs = promote(x1.x, xR...)
T = typeof(xs)
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() ;
 ]
2×2 Matrix{Vector{Int64}}:
  
  
``````
1 Like

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

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

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

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

julia> [; ]
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
@assert allequal(rows)
xs = promote(_xs...)
T = typeof(xs)
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[ 
 ]
2×2 Matrix{Vector{Int64}}:
  
  

``````
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