JuliaCon 2020 (times are in UTC)

A new Traits.jl: Easily dispatch on whatever you want

Julia has the power to define arbitrary dispatch helpers, like for iterators there is IteratorSize. My new package Traits.jl gives you the power to dispatch on such helpers directly as @traits f(a) where {Base.IteratorSize(a)::Base.HasShape} = "awesome!".


Dispatching on helper functions is extremely useful. Iterators are a perfect example: As everything can be an iterator we need to distinguish for some extra details in order to create optimal code. For instance whether something HasLength, HasShape{N}, IsInfinite, or has SizeUnknown. Binary functions also fall into this pattern - you may want to dispatch on whether something is isempty().

Without Traits.jl you would use nested functions for this, like

f(a) = f_(a, Base.IteratorSize(a), Val(isempty(a)))
function f_(a, ::Base.HasShape, ::Any)
  # do ... for something which HasShape
end
function f_(a, ::Base.HasShape, ::Val{false})
  # do ... for something which HasShape and is not empty
end

With the new Traits.@traits macro you can simply define them like

using Traits
@traits function f(a) where {Base.IteratorSize(a)::Base.HasShape}
  # do ... for something which HasShape
end
@traits function f(a) where {Base.IteratorSize(a)::Base.HasShape, !isempty(a)}
  # do ... for something which HasShape and is not empty
end

The @traits macro abstracts away the hidden complexity of the nested function, allowing you to seamlessly extend your traits-based methods.