The Type System and Type Hierarchy
Julia's types form a tree. At the top is Any. Inner nodes are
abstract types — categories like Number or AbstractString —
and the leaves are concrete types like Int64 and String, which
actual values have.
using InteractiveUtils # subtypes (loaded automatically in the REPL)
println(supertype(Int64))
println(supertype(Signed))
println(supertype(Integer))
println(supertype(Real))
println(supertype(Number))
println(subtypes(Integer))
println(Int64 <: Integer, " ", Int64 <: AbstractFloat, " ", Float64 <: Real)
println(isabstracttype(Number), " ", isconcretetype(Float64))
Signed
Integer
Real
Number
Any
Any[Bool, Signed, Unsigned]
true false true
true true
supertype(T)walks up the tree;subtypes(T)lists the children.subtypeslives in the InteractiveUtils standard library, which the REPL loads for you; scripts needusing InteractiveUtils.A <: Bmeans "A is a subtype of B".- You can't create a value of an abstract type — there's no plain
"Number" value, only
Int64s,Float64s, and so on.
The whole path
function ancestors(T)
path = [T]
while T !== Any
T = supertype(T)
push!(path, T)
end
return join(path, " <: ")
end
println(ancestors(Int8))
println(ancestors(Float32))
println(ancestors(String))
println(ancestors(Vector{Int}))
Int8 <: Signed <: Integer <: Real <: Number <: Any
Float32 <: AbstractFloat <: Real <: Number <: Any
String <: AbstractString <: Any
Vector{Int64} <: DenseVector{Int64} <: AbstractVector{Int64} <: Any
Type annotations
:: asserts or declares a type:
x = (1 + 2)::Int
println(x)
try
(1 + 2.0)::Int
catch err
println(sprint(showerror, err))
end
function half(n::Integer)
return n ÷ 2
end
println(half(9))
try
half(9.0)
catch err
println(typeof(err))
end
3
TypeError: in typeassert, expected Int64, got a value of type Float64
4
MethodError
- On an expression,
::Tchecks the value's type and throws if it's wrong. - On a function argument,
::Trestricts which values the function accepts. Using an abstract type likeIntegerkeeps the function general — it works forInt8,Int64,BigInt, and more.
Union types and Nothing
function find_user(id)::Union{String,Nothing}
users = Dict(1 => "ada", 2 => "alan")
return get(users, id, nothing)
end
println(find_user(1))
println(find_user(9) === nothing)
println(Union{Int,String} >: Int)
println(typeof(nothing), " ", Nothing <: Any)
ada
true
true
Nothing true
Union{A,B} is a type whose values are either A or B.
Union{T,Nothing} is the idiomatic "maybe a value" type.
Types are values
Types themselves are ordinary values you can store, pass, and compare —
typeof(Int) is DataType. That's what makes the next lesson,
multiple dispatch, possible.