Reviewing the many solutions in this thread, it is apparent that while there are many ways to create single-column matrices, there is no special syntax for this.

I wonder if this is really a problem. Many types in Base has no short syntax, they are just constructed with a constructor or a function for this purpose. I can imagine three possibilities:

Single-column matrices are not used frequently, eg because vectors are columns vectors in linear algebra, so they are rarely needed. When needed (eg for testing), there are workarounds. If a package uses a lot of these for some reason, they can define a function for it.

They are used frequently enough that a constructor syntax is warranted in base. We can either

a. co-opt one of the existing syntaxes for this, but this is proving to be difficult,

b. introduce a special function, eg colmx or something like that.

I am leaning towards 1, but perhaps I just have different use cases.

FWIW, I can’t remember ever creating an Nx1 Matrix in the past year or so and I’m almost thinking it could be better that it is hard to create them as they are so rarely useful.

If instead there actually is a need for some syntax, maybe the easiest would be to add a Matrix(v::Vector) method that would create an Nx1 matrix, just in the same way as Matrix(v::RowVector) would create a 1xN Matrix. On 0.6 and master it is a method error, so I guess it wouldn’t be a breaking change.

Part of the rationale for not having an easy way to create an N-by-1 matrix is that such matrices are usually better treated as vectors. However, the return values of expressions like maximum(A, 2) go against this philosophy. The returned array will always have a singleton dimension. It would seem natural to let the maximum function squeeze out this dimension. If this were the case, then the code from the original post would have worked as intended.

Of course it is sometimes useful to preserve the singleton dimension, but one could perhaps distinguish between maximum(A, (2,)) which would squeeze, and maximum(A, [2]) which keep the current behavior.

(Of course this would affect a lot of existing code, and it’s too late for new features for 1.0 anyways.)

I found this thread while scratching my head over array creation syntax. Why does Julia 1.1.0 still have two ways to make a vector, one way to make a 1×d array and zero ways to make a d×1 array? Can this still be changed?

I am not sure I understand why not having dedicated syntax for nx1 matrices is a problem,as you can still create them rather easily. I see this more as a documentation issue.

The only reason to prefer directly constructing the array (e.g. using the macro I proposed) is that it avoids allocating a temporary Vector and is therefore a bit faster:

julia> f1(x, y) = reshape([x, y], :, 1)
f1 (generic function with 1 method)
julia> f2(x, y) = @col [x, y]
f2 (generic function with 1 method)
julia> using BenchmarkTools
julia> @btime f1($1, $2)
53.962 ns (3 allocations: 192 bytes)
2×1 Array{Int64,2}:
1
2
julia> @btime f2($1, $2)
33.171 ns (1 allocation: 96 bytes)
2×1 Array{Int64,2}:
1
2

We simply don’t have enough surface syntax available to cover all the possible permutations of dimensionality and concatenation. In fact I’d re-phrase our current setup like this:

No concatenation

,-delimited vectors only

Concatenation:

space-delimited does horizontal concatenation (thus is 2+ dimensional)

;- and newline-delimited does vertical concatenation (thus is either 1- or 2+ dimensional)

Since we’re doing concatenation with ;, you can actually get the behavior you want like this:

It was discussed in the lead up to 1.0 whether [1; 2; 3] should construct a vector or a matrix. But note that there’s nothing special about two dimensions in concatenation syntax in general:

The [... ; ...] syntax calls vcat which does “concatenation along the first dimension”—regardless of how many dimensions the inputs have. If they’re vectors, it produces a vector, if they’re matrices, it produces a matrix, if they’re 3-tensors, it produces a 3-tensor, and so on. There does, however, have to be at least one output dimension since you’re concatenating at least two things vertically, so vcat of scalars does produce a vector. If we’d made [1; 2; 3] produce a 3×1 matrix then that would be arbitrarily treating 2-dimensionally arrays specially, which is a thing that Julia tries very hard to avoid and it would have to lower to something other than just plain vcat (or we’d have to make vcat treat matrices specially as well).

Another way of putting this is that this is the behavior of result = cat(dims=dim, args...) is that it produces a result with the following number of dimensions:

ndims(result) == max(dim, map(ndims, args)...)

Since [... ; ...] is syntax for vcat(...) which is just cat(dims=1, ...) that dictates that ndims([1; 2; 3]) == max(1, map(ndims, (1, 2, 3))...) == max(1, 0, 0, 0) == 1. If we special-cased [1; 2; 3] to produce a matrix then we’d ruin the above consistent rule and make the rule min(2, max(dim, map(ndims, args)...)) instead, which isn’t the worst but makes two dimensions special. It also leaves you without a syntax for vector concatenation which is itself a useful operation. So the choice here is between:

Having syntax for concatenating scalars/vectors into a vector;

Having syntax for concatenating scalars/vectors into an n×1 matrix.

It’s unclear to me that former is less useful or common than the latter.

That said, in practice I wonder if beginner and even somewhat experienced users think of the [x y ...] and [x, y, ...] syntax as concatenation, as opposed to just a vector/matrix constructor.

I am not saying it isn’t nice or consistent, but perhaps concatenation does not need its own special syntax, which could then obviate the need for the above consistency argument, and allow reusing it for “simple” cases like

I defined my own constructor to do that, I didn’t find one in base.

I don’t think using the constructor falls into the “zillion ways” to create a matrix, there should always be one available in my opinion, even though it might be verbose. Then the special syntax comes on top of that to make your life easier in some cases.