Julia: remove `Vector{T}()` constructor?

Created on 18 Mar 2017  Â·  21Comments  Â·  Source: JuliaLang/julia

julia> length(Array{Any}())
1

julia> length(Array{Any, 0}())
1

julia> length(Array{Any, 1}())
0

julia> length(Vector{Any}())
0

Not sure if they are the expected results, but I did expect that length(Array{Any}()) = 0

decision

Most helpful comment

The Array{T}() constructor is not "implicit" – it is the logically consistent zero-dimensional instance of the generic Array{T}(dims...) family of array constructors. Excluding the zero-dimensional case would be the inconsistent thing to do here.

All 21 comments

This is expected. This is the difference between creating a zero-dimensional array (which has size () and exactly one element) and a zero-length one-dimensional array (which has size (0,)).

That said, the existence of the Vector{Any}() constructors makes this more confusing. Ref: https://github.com/JuliaLang/julia/pull/20250#issuecomment-275766438. Have we come to a conclusion about the existence of Vector{Any}()? I think I'd argue for its removal.

Ai,...it makes sense as prod(()) is 1. However, I do find that Vector{Any}() is handy in a lot of other cases.

I feel that Vector{T}() is the right constructor for an empty, resizable list - I use it quite often that way, followed by push!, etc. Note that a similar constructor exists for Dict and other resizable containers.

I think that the moment when we implement Buffer and have non-resizable Vector and a resizable container like List or something, then it would be the perfectly natural to drop this constructor from Vector.

What I see here which seems wrong is that the empty Array{T}() constructor returns a zero-D array by default. This constructor could be dropped in favor of Array{T, 0}(), and IMO the OP would become a bit less confusing.

I agree with @andyferris that the implicit 0-d array constructor Array{T}() is confusing.
Replacing the implicit constructor of 0-d arrayArrayr{T}() by Array{T, 0}() would be less confusing.
It doesn't mean to remove the function Arrayr{T}() as a whole but only to drop the empty argument signature of Arrayr{T}() in favor of the explicit constructor Array{T, 0}().

The Array{T}() constructor is not "implicit" – it is the logically consistent zero-dimensional instance of the generic Array{T}(dims...) family of array constructors. Excluding the zero-dimensional case would be the inconsistent thing to do here.

Then I would argue to remove the calls of Array{T,1}() and Array{T,2}() for creating zero elements multi dimensional arrays. They should be called with the corresponding dimensions explicitly, e.g. Array{T,2}(0,0).

I would imagine we'll be keeping Array{T,N}() constructors, but "vector" is generally easy to confuse with the mathematical kind; perhaps we could make Array{T}() be equivalent to Array{T,1}() ?

+1 for the idea suggested by @H-225. I often construct empty 1-D Arrays and almost never 0-D Arrays, so this syntax could be more convenient. (I know, we use numbers all the time, but we tell Julia that they are things like Float64 or not Array{Float64, 0}. Given the new broadcasting syntax, I don't see that we would ever need a 0-d Array

All the array constructors take either a size tuple or an argument list of dimension lengths. If you omit the dimensionality in the type, then the dimensionality is simply the length of the tuple or number of arguments. If you include the dimensionality, then the arguments must match. Array{T,1}() is the only odd man out here. The Array{T,2}() constructor has been removed on 0.6.

I'd argue that this case is distinctly different from the constructors for other resizable collections because those constructors frequently take an iterable list of contents for them to contain. In that case it makes a lot more sense that a no-argument default is an empty collection.

I think the solution here is the deprecation of Array{T,1}() followed by a helpful MethodError print out once the deprecation goes away. We already have a very nice syntax for an empty vector: [] or T[].

I take your point, @mbauman. I had forgotten about the possibility of T[]. And it does make sense to eliminate as many exceptions to the rules as possible.

So the "functional" (as opposed to "literal") syntax would be Vector{T}(0)?

... it is the logically consistent zero-dimensional instance of the generic Array{T}(dims...) family of array constructors.

Ah, that's very true - I was thinking of the tuple form (e.g. Array{T}(()) obviously is zero-D).

I'd argue that this case is distinctly different from the constructors for other resizable collections because those constructors frequently take an iterable list of contents for them to contain

That's an interesting one - turning this on its head, why shouldn't Array also accept a Generator or similar in its constructor (e.g. instead of comprehensions going through collect)? It seems Array is an odd-one-out in the sense that there aren't such constructors which initialise values.

Array{Int,2}() is already deprecated. The only cases where you can supply no dimensions are:

  • the zero-dimensional instance of the standard constructors: Array{T,0}() and Array{T}()
  • the one-dimensional case: Array{T,1}().

The latter is mildly exceptional, but seems practical and commonly used. I don't really see why it's a pants on fire issue to delete this method.

I don't really see why it's a pants on fire issue to delete this method.

This is my point earlier. It would go away naturally if/when Vector looses its resizing capability (assuming that is still the plan) because patterns where this is actually useful would change to a constructor for a different type like List{T}() (speculatively named), so the question is: why not be patient until then?

Closing this, given #22717

Actually, I have no idea why this thread got evolved from removing Array{T}() to removing Vector{T}().

My original idea was to remove - Array{T}(), this confusing constructor for constructing zero dimensional one element array.

EDIT: just re-read above, my mind was also changing, I did mention removing Vector{T}. But still, Array{Any}() to create zero-dimensional one-element array is quite confusing.

Agreed, Ref does everything that Array{T}() does, it should be deprecated since it is confusing, as you mention, and those usages should instead be Ref's. @randy3k perhaps open a new issue with this more clearly articulated.

Removing only Array{T}() while keeping Array{T}(d1), Array{T}(d1, d2) and so on, is not going to happen. Array{T}() is the natural, logical constructor for a zero-dimensional array. Perhaps some people find it confusing and don't want to use it – that's fine, then don't use it. Having these kinds of ad hoc, inconsistent corner cases that seemed more convenient or less confusing to someone at some point is exactly what makes writing generic code that just works a nightmare in other systems.

Please do not open a new issue that suggests only removing Array{T}() – it will simply be closed. If you want to propose deprecating all Array{T}(dims...) constructors and only using Array{T}(dims) where dims is a tuple, that's a different story. I don't think that will be popular, but at least it's consistent.

Fair point, I will not pursue the issue further. However, I am curious is there actually a use case for zero-dimensional array's which is not more appropriately a Ref?

There are couple of moments that I needed to create empty arrays (vectors) and wrote Array{T}() and spent 15 mins to figure out the length of Array{T}() is not zero. The issue is not "don't use it when it is confusing", the issue is "I don't know I have used it".

Ya, deprecating all Array{T}(dims...) is indeed an solution. For vectors and matrices, there are still constructors: Vector{T}(n) and Matrix{T})(m, n). It also eliminates the confusing Array{T}().

If we eliminated Array{T}(dims...) then Vector{T}(n) and Matrix{T}(m, n) would also go away – Vector{T} and Matrix{T} are just aliases for Array{T,1} and Array{T,2}. You would have to write Vector{T}((n,)) and Matrix{T}((m, n)). That's why I don't think this would be popular.

I suppose that we could only allow Array{T,n}(dims...) but not Array{T}(dims...) which would preserve Vector{T}(n) and Matrix{T}(m, n), but that just seems kind of annoying and would mean you're have to write Array{T,3}(d1, d2, d3) or Array{T}((d1, d2, d3)) when constructing a 3-tensor, both of which seem pointlessly irritating.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

omus picture omus  Â·  3Comments

TotalVerb picture TotalVerb  Â·  3Comments

ararslan picture ararslan  Â·  3Comments

musm picture musm  Â·  3Comments

omus picture omus  Â·  3Comments