Skip to content

Commit

Permalink
Merge pull request #20 from mrufsvold/add-dev-docs
Browse files Browse the repository at this point in the history
Add-dev-docs
  • Loading branch information
mrufsvold authored May 30, 2024
2 parents 194d5b2 + ef315dd commit 19478ae
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 0 deletions.
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ SumTypes = "0.5"
Test = "1.6"
TestItemRunner = "0.2"
TestItems = "0.1"
Tricks = "0.1"
julia = "1.11"

[extras]
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,6 @@ end
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.
1 change: 1 addition & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ makedocs(;
),
pages=[
"Home" => "index.md",
"Developer Documentation" => "developer_docs.md",
],
)

Expand Down
45 changes: 45 additions & 0 deletions docs/src/developer_docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Developer Documentation
# Introduction
There are two fundamental pieces of this package:
1) Constructing `DuckType`s and their `Behavior`s
2) Defining methods which can be dispatched on `DuckType`s
# Constructing `DuckType`s
## `Behavior`s
A `Behavior` represents a method that must be implemented for a `DuckType`. It has the form:
```julia
Behavior{F, T<:Tuple}
```
where `F` is the type of the function for this method and `T` is the type parameters for the arguments of the method. However, instead of having a specific `DuckType` as a type parameter, it is replace with `DuckDispatch.This`. `This` is a placeholder that lets any composed `DuckType` quickly insert itself when checking for matching methods.
## `DuckType`s
A `DuckType` has the following anatomy:
```julia
DuckType{
Union{Behavior1, Behavior2, ...},
Union{ComposedDuckType1, ComposedDuckType2, ...}
}
```
The first type parameter is a union of `Behavior` (see below) types that were added to the `DuckType` by the current definition.

A user's specific `DuckType` is a struct which subtypes the `DuckType` that is composed of all the `Behavior`s they specify.

We can check if a specific type, `T`, implements all the `Behavior`s required by a `DuckType` by calling `quacks_like(SomeDuckType, T)`

## `Guise`
A `Guise` is a wrapper which allows a type to "pass" as a `DuckType` for method dispatching. It looks like this
```julia
Guise{<:DuckType, T}
```
Users should not normally be constructing a `Guise` directly. This is handled by the dispatching machinery provided by `DuckDispatch.jl`.

## `@duck_type`
This macro constructs the type definition for a new duck type and a method for each behavior that dispatches on a `Guise{ThisDuckType, <:Any}`. This specific method simply unwraps the arguments and passes on to the real method.

It also implements a fallback `Guise{<:Any, <:Any}` version of the method which recursively descends through all the composed `DuckType`s and checks if there is an implied `DuckType` which has a `Behavior` for this method.

# `@duck_dispatch`
When we want to dispatch a method using a `DuckType`, we use `@duck_dispatch` to build the necessary infrastructure. Currently, this macro does a few things:

1) Checks to make sure it won't overwrite a regular generic method
2) Defines the user's method, replacing `DuckType`s with `Guise{DuckType}`s
3) Constructs a global constant with the current list of `DuckType` dispatched method signatures. This allows us to avoid calls to `methods` at runtime.
4) Constructs a generic method with the correct number of arguments to catch calls and do the `Guise` wrap operations.

0 comments on commit 19478ae

Please sign in to comment.