Why does a = Vector{<:Real}(undef, 2) fail?

question

#1

Why does a = Vector{<:Real}(undef, 2) fail, giving the following error?
MethodError: no method matching Array{#s1,1} where #s1&lt;:Real(::UndefInitializer, ::Int64)

(Julia version 1.0)


#2

Vector{<:Real} (short of Vector{T} where T<:Real) is not a concrete type and in this case it’s unclear what exactly you want to construct so there isn’t a method defined for this to guess what you want.


#3

But, c = Vector{Real}(undef, 2) works, while Real isn’t a concrete type.


#4

That’s exactly why I spelled out the type for you. Real isn’t a concrete type but Vector{Real} is. Vector{T} where T<:Real isn’t a concrete type because it’s a class (UnionAll) of types constraint by the where


#5

Vector{Real} is a concrete type, a vector holding any Real.

What would be the element type of Vector{<:Real} ? You haven’t specified T.


#6

Thank you for the comment. I wasn’t aware a = Vector{T} where T<:Real was of UnionAll. When I checked d = Vector{T} where T<:Real; typeof(d) , it’s UnionAll, indeed :slight_smile:


#7

Actually, I was creating a vector of vectors vv = Vector{Vector{<:Real}}(undef, 2), which worked. So, I assumed vv[1] = Vector{<:Real}(undef, 2) would work. Well, it seems I was wrong.

In practice, I’ll do vv[1] = Vector{Real}(undef, 2) and will have no problem.

Now, it’s still unclear to me why vv above works… when I checked the type of vv above, it’s DataType.


#8

And that’s exactly why I always hated the <: notation… Vector{Vector{<:Real}} is Vector{Vector{T} where T<:Real}, i.e. a Vector of the abstract type Vector{T} where T<:Real. It is not Vector{Vector{T}} where T<:Real which would be an abstract type (UnionAll). <:T isn’t a value (there’s no value X where Vector{X} is Vector{<:Real}) rather a syntax that moves out of the enclosing{}. However, it only move one level of {} making it really confusing for beginners (and expers when not paying attention).


#9

Yes I can see why this seems confusing.

One way to look at it is you can create a concrete Vector with an abstract element type as long as that element type is well specified.
However you can’t create a Vector with “unspecified” element type.

Perhaps related, compare:

Vector{Vector{Real}}             # concrete
Vector{Vector{T} where T<:Real}  # concrete
Vector{Vector{T}} where T<:Real  # abstract, T not specified

#10

Thank you for the comments. Now I understand the subtle syntax issue much better.