JULIA / CHAPTER 08
Parametric storage and flexible interfaces
AdvancedKeep concrete storage while accepting families of numeric inputs.
By the end of this chapter
- Use type parameters in composite types
- Explain invariant container parameters
- Accept numeric vectors with a bounded element type
The idea
A parametric type records a relationship between its fields and a type parameter. Box{Int} and Box{Float64} are different concrete types, allowing each value’s representation to remain specific. A field declared with an unconstrained abstract type has a different storage contract from a field declared as T in a type parameterized by T. Prefer a representation that states the relationship your operations actually require.
Julia’s ordinary parametric types are invariant: Vector{Int} is not a subtype of Vector{Real}, even though Int is a subtype of Real. A method intended to accept a vector of any real element type can use AbstractVector{<:Real}. This describes a family of vector types without demanding that every caller construct a Vector{Real}. Keep accepted interfaces broad while keeping stored data appropriately concrete.
struct Box{T}
value::T
end
println(Box(3).value)
println(Box(3.0) isa Box{Float64})
println(Vector{Int} <: Vector{Real})3 true false
Constructor inference produces concrete parameterizations. Subtyping of element types does not make the corresponding invariant vector types subtypes.
Try it yourself
Define a parametric reading type and a function accepting any AbstractVector whose elements are Real.
Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.
CHECK YOUR UNDERSTANDING