Generated Functions & Traits

@generated functions produce code based on argument types, at compile time:

26.1 Generated functions

@generated functions produce code based on argument types, at compile time:

Use sparingly; constant propagation and ntuple/recursion often suffice.

@generated function tuple_sum(t::NTuple{N, T}) where {N, T}
    ex = :(zero(T))
    for i in 1:N
        ex = :($ex + t[$i])
    end
    return ex                    # fully unrolled sum
end
tuple_sum((1, 2, 3, 4))

26.2 Holy traits (trait-based dispatch)

Dispatch on properties rather than type hierarchies:

Base uses this pattern for IndexStyle (IndexLinear / IndexCartesian), IteratorSize, IteratorEltype, BroadcastStyle. SimpleTraits.jl and WhereTraits.jl help.

abstract type Speed end
struct Fast <: Speed end
struct Slow <: Speed end

speed(::Type) = Slow()                       # default trait
speed(::Type{<:AbstractRange}) = Fast()

lookup(x) = lookup(speed(typeof(x)), x)      # trait dispatch
lookup(::Fast, x) = "O(1) path"
lookup(::Slow, x) = "O(n) path"

lookup(1:10), lookup([1, 2, 3])

26.3 Other advanced dispatch patterns

Value types: Val{N} to dispatch on compile-time constants.

@nospecialize to reduce compilation for functions with many argument types.

Type parameters as computation: StaticArrays encode size in the type.

Callable structs and function wrappers (FunctionWrappers.jl) for dynamic callbacks.