Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mrufsvold/duckdispatch.jl
If it quacks like a duck... dispatch on it!
https://github.com/mrufsvold/duckdispatch.jl
ducktyping julia multiple-dispatch
Last synced: about 1 month ago
JSON representation
If it quacks like a duck... dispatch on it!
- Host: GitHub
- URL: https://github.com/mrufsvold/duckdispatch.jl
- Owner: mrufsvold
- License: mit
- Created: 2024-05-10T21:26:49.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2024-05-31T17:05:50.000Z (6 months ago)
- Last Synced: 2024-10-12T19:20:46.019Z (about 1 month ago)
- Topics: ducktyping, julia, multiple-dispatch
- Language: Julia
- Homepage:
- Size: 229 KB
- Stars: 15
- Watchers: 1
- Forks: 0
- Open Issues: 8
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# DuckDispatch.jl
[![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://mrufsvold.github.io/DuckDispatch.jl/stable/)
[![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://mrufsvold.github.io/DuckDispatch.jl/dev/)
[![Build Status](https://github.com/mrufsvold/DuckDispatch.jl/actions/workflows/CI.yml/badge.svg?branch=master)](https://github.com/mrufsvold/DuckDispatch.jl/actions/workflows/CI.yml?query=branch%3Amaster)
[![Coverage](https://codecov.io/gh/mrufsvold/DuckDispatch.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/mrufsvold/DuckDispatch.jl)
[![Aqua](https://raw.githubusercontent.com/JuliaTesting/Aqua.jl/master/badge.svg)](https://github.com/JuliaTesting/Aqua.jl)`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.
# Why?
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:
1) compile time guarantees that there won't be any method errors for the `Behavior`s defined for the `DuckType`
2) helpful errors for calls to a method that is not defined for the `DuckType`
3) a method signature that is more informative about the meaning of is arguments# The Basics
To define an `Iterable` `DuckType`, we can do the following:```julia
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)}
end
```Now, we can create a new function that dispatches on this `DuckType`:
```julia
@duck_dispatch function my_collect(arg1::Iterable{T}) where {T}
v = T[]
for x in arg1
push!(v, x)
end
return v
endusing 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`!
```julia
@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]
end
```# More Information
See [the developer documentation](./docs/src/developer_docs.md) for more information the internals of this package.