Why doesn't multi-dimensional Array have zero-argument constructor?

I can create an empty one-dimensional array with a zero-argument constructor:

julia> Vector{Float64}()
Float64[]

But I can’t create an empty multi-dimensional array with a zero-argument constructor:

julia> Array{Float64,2}()
ERROR: MethodError: no method matching Matrix{Float64}()
...

Is there a reason why the zero-argument constructor is not implemented for multi-dimensional arrays? We can certainly create empty multi-dimensional arrays by

julia> Float64[;;]
0×0 Matrix{Float64}

julia> Float64[;;;]
0×0×0 Array{Float64, 3}

so I don’t think there is any fundamental obstacle to implementing it, but I’m not sure.

There is a unique empty vector (with a given element type), but there are many different empty n-dimensional arrays for n > 1. E.g.

julia> fill(0.0, 0, 1, 2)
0×1×2 Array{Float64, 3}

julia> fill(0.0, 2, 1, 0)
2×1×0 Array{Float64, 3}

Emptiness is determined by one of the dimensions being zero, but the other dimensions can have any size at all. For n = 1 this dictates that the one dimension have size zero, but for larger n the other dimensions are undetermined.

13 Likes

You can also push! to an empty vector, which makes it much more common to use an empty one.

3 Likes

But one could say that there is one canonical empty array, where all dimensions are zero, and use that.

1 Like

Agreed, but then there’s also the zero-dimensional corner case where there is no empty array.

1 Like

That would be a different type, though.

Well, yes, Array{T, N} for different T and N are all different types, so I’m not sure I see your point.

I’m not sure I understood yours either to be honest:

I took this to mean that one possible zero-dimensional array would be the one where there is no value at all, the absence of an object/value, and that you considered that case as an alternative to 0x0 as the canonical case for Array{Float64, 2}(). And then I responded to that by saying that would not preserve the type of the (zero-argument) constructor.

But I perhaps misunderstood?

My point was just that if the idea of the zero-argument constructor is to create an empty array, then Array{T, 0} would be a corner case since they don’t have any empty instances.

1 Like

Ah, zero-dimensional, not zero-size. Yeah, not sure about that one.

I think the issue this highlights is that if you’re going to have a convention for a specific empty array being “the standard one” then it’s a bit of an odd smell that in one of the cases (zero dimensions) there is no such array. It’s one of those cases of “if you do this it works… oh but not in this one case, then it doesn’t.” If something can’t really be a consistent convention maybe it shouldn’t be a convention in the first place.

Interestingly, for a given value, there is a unique single-element array of every dimensionality containing just that value because there’s only one way for the product of n dimensions to be 1.