The Julia style guide says,
For example, don’t declare an argument to be of type Int
or Int32
if it really could be any integer, expressed with the abstract type Integer
(Numbers · The Julia Language)
However, this creates some issues when dealing with Dictionaries. As an example:
x = Dict(1=>[1,2,3])
display(x isa Dict{Integer,Vector{Integer}})
display(x isa Dict{Int64,Vector{Int64}})
The first option (using Integer
) returns false
. The second option (using Int
) returns true
. Any thoughts here?
This is just that Julia’s types are invariant. You want Dict{<:Integer, Vector{<:Integer}}
.
4 Likes
Adding the <:
continues to return false
julia> x = Dict(1=>[1,2,3])
Dict{Int64,Array{Int64,1}} with 1 entry:
1 => [1, 2, 3]
julia> x isa Dict{<:Integer, <:Vector{<:Integer}}
true
Here Vector{<:Integer}
isa UnionAll
type
julia> Vector{<:Integer}
Array{#s3,1} where #s3<:Integer
and Vector{Int}
is a concrete type from the union.
1 Like
Ok. Adding the additional <:
before Vector
works. I guess for Dictionaries its just easier to disregard the Julia style guide and use Int
instead of Integer
with all those <:
.
Thanks for the help.
Yes you should absolutely use concrete parametric types while creating objects, eg Dicts. The suggestion for abstract types is usually for function arguments
3 Likes
No, the style guide is correct, what you are missing is the concept of invariance, see
https://docs.julialang.org/en/v1/manual/types/#Parametric-Abstract-Types-1
The solution given by @jishnub is the correct way to dispatch on subtypes of a parametric type without narrowing down to a concrete one.
1 Like
Good point. I see that there is a clear warning on this in the documentation right above the section on parametric abstract types. Thanks!
Concrete Point
types with different values of T
are never subtypes of each other:
julia> Point{Float64} <: Point{Int64}
false
julia> Point{Float64} <: Point{Real}
false
Warning
This last point is very important: even though Float64 <: Real
we DO NOT have Point{Float64} <: Point{Real}
.