DuckDispatch.jl is an experimental package which attempts to make it easy to dispatch a method based on the behavior of a type, not its place in the type hierarchy. At a high-level, it allows the user to define a number of method signatures which constitute a DuckType. Then, any type which has an implementation for those methods can be wrapped in a Guise{D<:DuckType, T}. This Guise type is then hooked into the normal Julia dispatch machinery.
It often does not matter if an input is of a specific type (like a vector, a channel, or a set); it matters that it is has a certain functionality (like iterable). While creating a method with a completely generic argument will work, it also provides no guarantees that the input will have the necessary methods.
By dispatching on a DuckType, we get:
- compile time guarantees that there won't be any method errors for the
Behaviors defined for theDuckType - helpful errors for calls to a method that is not defined for the
DuckType - a method signature that is more informative about the meaning of is arguments
To define an Iterable DuckType, we can do the following:
using DuckDispatch
@duck_type struct Iterable{T}
function Base.iterate(::This)::Union{Nothing, Tuple{T, <:Any}} end
function Base.iterate(::This, ::Any)::Union{Nothing, Tuple{T, <:Any}} end
@narrow T -> Iterable{eltype(T)}
endNow, we can create a new function that dispatches on this DuckType:
@duck_dispatch function my_collect(arg1::Iterable{T}) where {T}
v = T[]
for x in arg1
push!(v, x)
end
return v
end
using Test
@test my_collect((1,2)) == [1,2]
@test my_collect(1:2) == [1,2]
@test my_collect((i for i in 1:2)) == [1,2]Iterable is pretty limited without length. We can compose it with some new behaviors to build a more feature-rich DuckType!
@duck_type struct FiniteIterable{T} <: Union{Iterable{T}}
function Base.length(::This)::Int end
@narrow T -> FiniteIterable{eltype(T)}
end
@duck_dispatch function my_collect(arg1::FiniteIterable{T}) where {T}
return T[x for x in arg1]
endSee the developer documentation for more information the internals of this package.