We are designing a generic interface for a library to take expectations of distributions , and would love some help trying to get the dispatch design correct. The basic idea is that there are a set of different algorithms (which we are writing) which can be applied to different types (which come from other libraries). There is a default algorithm that works for any of the types, but we want to change which is the default algorithm used based on the particular type. Lets start by defining some abstract types to help us out:

```
#These come from other libraries...
abstract type AbstractValue end
type Value1 <: AbstractValue end
type Value2 <: AbstractValue end
#These are in our package, and we can define these in whatever way is easiest.
abstract type AbstractAlgorithm end
type Algorithm1 <: AbstractAlgorithm end
type Algorithm2 <: AbstractAlgorithm end
```

The set of algorithms implementations is then a bunch of `f(v::AbstractValue, alg::AbstractAlgorithm)`

A few of the principles (which I will condense to a test-suite for the impatient) are

- There always needs to be a concrete AbstractValue (i.e., think of this as algorithms on Distributions.jl)
- For any
`AbstractValue`

without any further specialization, the algorithm`Algorithm1`

always works, and we want it to be chosen by default - While
`Algorithm1`

is always possible for any distribution,`Algorithm2`

is only defined for some`AbstractValue`

. In particular, assume that it isnâ€™t meaningful for`Value2`

- For a
`Value1`

we want to change the default algorithm to`Algorithm2`

- There are different default parameters for
`Algorithm1`

and`Algorithm2`

, which could have different names or values.- Assume that the default parameter is
`N=10`

for`Algorithm1`

and`N=5`

for`Algorithm2`

- It would be nice if Default values were by algorithm-value combination, but can live without it

- Assume that the default parameter is
- It is preferred if algorithm parameters use keyword arguments, but not strictly necessary
- We donâ€™t need to worry about there being extra, unused, parameters

- It would be nice if we didnâ€™t need to force a particular set of parameter names to be shared by Algorithms (i.e. use variable argument keywords)
- We expect to add in many more AbstractValue types, and a couple more Algorithm types

## A Test Suite

```
using Base.Test
v1 = Value1()
v2 = Value2()
@test f(v1) == f(v1, Algorithm2, N=5) #i.e. defaults to Algorithm 2 with N=5 as the default
@test f(v1, N = 7) == f(v1, Algorithm2, N=7) #Can change the default value
@test f(v1, Algorithm1) == f(v1, Algorithm1, N=10) #can use use Algorithm1 (with the different default)
@test f(v2) == f(v2, Algorithm1, N=10) #i.e. uses algorithm 1 by default
@test f(v2, N = 8) == f(v2, Algorithm1, N=8) #Can change the default value
@test_throws f(v2, Algorithm2) #Not defined! Should throw
```

I tried to come up with something that would fulfill the test suite, but cannot figure out how to organize the functions, etc. to avoid ambiguity issues. Here was my (**not passing the test**) attempt

```
#Forwards based on default algorithm
f(v::AbstractValue, alg::Type{<:AbstractAlgorithm} = Algorithm1; kwargs...) = f(v,alg, kwargs...)
f(v::Value1, alg::Type{<:AbstractAlgorithm} = Algorithm2; kwargs...) = f(v,alg, kwargs...)
#Implementations
f(v::AbstractValue, alg::Type{Algorithm1}; N=10, kwargs...) = (1,N) #i.e. algorithm 1, N=N
f(v::Value1, alg::Type{Algorithm2}; N=5, kwargs...) = (2,N) #i.e. algorithm 2 specialization, N=N
```