Skip to content
pao edited this page Apr 16, 2012 · 5 revisions

Patterns in Julia

Climbing the type hierarchy

The base library of Julia contains a method which finds the element type of an array. This dispatch is fine for instances of AbstractArray or any of its children.

eltype{T,n}(::AbstractArray{T,n}) = T

But what about if you supply a type instead of an instance? Naively, you could do this, and duck type the children:

eltype{T<:AbstractArray}(::Type{T}) = T.parameters[1] # BAD

But that relies on all the concrete implementations working that way, so isn't particularly generic.

Instead, provide an implementation for the highest type in the hierarchy:

eltype{T,n}(::Type{AbstractArray{T,n}}) = T

And for children, go one step up the type chain. If you haven't reached the highest type in the chain yet, this will recursively call itself until eventually the first dispatch matches.

eltype{T<:AbstractArray}(::Type{T}) = eltype(super(T))

Pattern matching on sum types

In languages with algebraic data types, a common technique is to create a simple sum type—a type that is exactly one of its children, but contains no fields—and perform a pattern match to run different code depending on which type you get. It is possible to perform a similar operation with multiple dispatch.

The Options framework uses this to distinguish different ways of dealing with potentially unused options to a function.

First, declare the types:

abstract OptionsChecking
type CheckNone <: OptionsChecking; end
type CheckWarn <: OptionsChecking; end
type CheckError <: OptionsChecking; end

You can then write multiple methods to match on the type when it is appropriate to do so.

function docheck(o::Options{CheckNone},checkflag::Vector{Bool})
    clearcheck(o,checkflag)
end
function docheck(o::Options{CheckWarn},checkflag::Vector{Bool})
    unused, msg = docheck_common(o,checkflag)
    if any(unused)
        println("Warning: ",msg)
    end
    clearcheck(o,checkflag)
end
function docheck(o::Options{CheckError},checkflag::Vector{Bool})
    unused, msg = docheck_common(o,checkflag)
    clearcheck(o,checkflag) # in case it's in a try/catch block...
    if any(unused)
        error(msg)
    end
end
Clone this wiki locally