Why does a = Vector{<:Real}(undef, 2)
fail, giving the following error?
MethodError: no method matching Array{#s1,1} where #s1<:Real(::UndefInitializer, ::Int64)
(Julia version 1.0)
Why does a = Vector{<:Real}(undef, 2)
fail, giving the following error?
MethodError: no method matching Array{#s1,1} where #s1<:Real(::UndefInitializer, ::Int64)
(Julia version 1.0)
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.
But, c = Vector{Real}(undef, 2)
works, while Real isn’t a concrete type.
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
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
.
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
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.
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).
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
Thank you for the comments. Now I understand the subtle syntax issue much better.
As mentioned above, use of <: such as Vector{Matrix{<:Real}} is a bit confusing…
a = [[1 2 3;4 5 6],[3 2 1;6 5 4]]
function temp(a::Vector{Matrix{<:Real}})
a
end
temp(a)
MethodError: no method matching temp(::Array{Array{Int64,2},1})
Closest candidates are:
temp(::Array{Array{#s1,2} where #s1<:Real,1}) at In[1]:4
It's the same as
function temp1(a::Vector{Matrix{T} where T<:Real})
a
end
temp(a)
MethodError: no method matching temp(::Array{Array{Int64,2},1})
Closest candidates are:
temp(::Array{Array{#s1,2} where #s1<:Real,1}) at In[1]:4
However, this works:
function temp2(a::Vector{<:Matrix{<:Real}})
a
end
temp2(a)
2-element Array{Array{Int64,2},1}:
[1 2 3; 4 5 6]
[3 2 1; 6 5 4]
I sort of understand why, but will appreciate a good explanation.
As suggested in one of the comments above in this thread, maybe better avoid such use of <: if I don’t understand it very well? The following function works well and easier to understand.
function temp3(a::Vector{Matrix{T}} where T<:Real)
a
end
temp3(a)
2-element Array{Array{Int64,2},1}:
[1 2 3; 4 5 6]
[3 2 1; 6 5 4]
Because parametric types in Julia are invariant. From documentation:
This last point is very important: even though
Float64 <: Real
we DO NOT havePoint{Float64} <: Point{Real}
.
So translating this to your case:
Vector{Matrix{Int}} <: Vector{Matrix{<:Real}}
is false.Vector{Matrix{Int}} <: Vector{<:Matrix{Real}}
is false.But if you want covariance then
Vector{Matrix{Int}} <: Vector{<:Matrix{Int}}
is trueVector{Matrix{Int}} <: Vector{<:Matrix{<:Real}}
is trueVector{Matrix{Int}} <: Vector{Matrix{T}} where T<:Real
is true