Composite Types & Constructors
Immutable structs are efficient (can be stack-allocated / stored inline in arrays).
14.1 Immutable structs
Immutable structs are efficient (can be stack-allocated / stored inline in arrays). Prefer them.
struct Point
x::Float64
y::Float64
end
p = Point(1.0, 2.0)
p.x # 1.0
# p.x = 3.0 # ERROR: immutable
fieldnames(Point) # (:x, :y)
Point(1, 2) # converted to Float64 automatically14.2 Mutable structs
Base.@kwdef / @kwdef (1.9+) gives keyword constructors with defaults:
mutable struct Account
owner::String
balance::Float64
end
acc = Account("Ann", 100.0)
acc.balance += 50@kwdef mutable struct Config
host::String = "localhost"
port::Int = 8080
debug::Bool = false
end
Config(port=9000)14.3 Parametric structs
struct Point2D{T<:Real}
x::T
y::T
end
Point2D(1, 2) # Point2D{Int64}
Point2D(1.0, 2.5) # Point2D{Float64}
Point2D{Float32}(1, 2)
struct Pair2{A, B}
first::A
second::B
end14.4 Constructors
struct Circle
r::Float64
function Circle(r) # inner constructor: enforce invariants
r < 0 && throw(ArgumentError("radius must be non-negative"))
new(r)
end
end
Circle() = Circle(1.0) # outer constructor (convenience)
Circle(d::Dict) = Circle(d["r"])
struct Interval{T}
lo::T
hi::T
Interval{T}(lo, hi) where {T} = lo <= hi ? new{T}(lo, hi) : error("lo > hi")
end
Interval(lo::T, hi::T) where {T} = Interval{T}(lo, hi)14.5 Customizing display, equality, and copying
Base.show(io::IO, p::Point) = print(io, "Point(", p.x, ", ", p.y, ")")
Base.:(==)(a::Point, b::Point) = a.x == b.x && a.y == b.y # default for immutables is field-wise ===
Base.hash(p::Point, h::UInt) = hash(p.x, hash(p.y, h))
Base.copy(a::Account) = Account(a.owner, a.balance)14.6 Properties & accessors
Accessors.jl / Setfield.jl allow "updating" immutable structs: @set p.x = 5.0.
Base.getproperty(p::Point, s::Symbol) = s === :r ? hypot(getfield(p, :x), getfield(p, :y)) : getfield(p, s)
Base.propertynames(::Point) = (:x, :y, :r)