## KeywordCalls.jl

KeywordCalls makes it easy to define a method taking a NamedTuple considered as a an unordered collection of bound variables. The required redirection is done at compile time, so there's no runtime overhead.
Author cscherrer
Popularity
20 Stars
Updated Last
10 Months Ago
Started In
April 2021

# KeywordCalls

In Julia, the named tuples `(a=1, b=2)` and `(b=2, a=1)` are distinct. In some cases, it's convenient to define a method for each set of names, rather than each particular ordering.

KeywordCalls.jl lets us do this, and allows specification of a "preferred ordering" for each set of arguments.

On Julia 1.6, this can be done with no allocation! This is included in the unit tests. Unfortunately, the current implementation leads to allcoation in Julia 1.4 and 1.5. We hope this can be improved for better backward-compatibility, but for now we recommend using 1.6 if possible.

KeywordCalls is very light weight:

```julia> @time_imports using KeywordCalls
[ Info: Precompiling KeywordCalls [4d827475-d3e4-43d6-abe3-9688362ede9f]
0.3 ms  Compat
0.3 ms  Tricks
0.2 ms  KeywordCalls```

## `@kwcall`

If we define

```f(nt::NamedTuple{(:b, :a)}) = println("Calling f(b = ", nt.b,",a = ", nt.a, ")")

@kwcall f(b,a)```

Then

```julia> f(a=1,b=2)
Calling f(b = 2,a = 1)

julia> f(b=2,a=1)
Calling f(b = 2,a = 1)```

We can define a new method for any set of arguments we like, including default values. If (after the above) we also define

```f(nt::NamedTuple{(:c, :a, :b)}) = println("The sum is ", sum(values(nt)))

@kwcall f(c=0,a,b)```

then

```julia> f(a=1,b=2)
The sum is 3

julia> f(a=1,b=2,c=3)
The sum is 6```

## `@kwalias`

It's often useful to allow multiple names to be mapped to the same interpretation. For that, we have `@kwalias`:

```julia> using KeywordCalls

julia> @kwcall f(c=0,a,b)
f (generic function with 3 methods)

julia> @kwalias f [
α     => a
alpha => a
β     => b
beta  => b
]

julia> f(α=2,β=3)
The sum is 5

julia> f(α=2,beta=3)
The sum is 5```

## `@kwstruct`

KeywordCalls is especially powerful when used for structs. If you have

```struct Foo{N,T} [<: SomeAbstractTypeIfYouLike]
someFieldName :: NamedTuple{N,T}
end```

then

```julia> @kwstruct Foo(μ,σ=1)
Foo

julia> Foo(σ=2,μ=4)
Foo{(:μ, :σ), Tuple{Int64, Int64}}((μ = 4, σ = 2))```

In MeasureTheory.jl, we use this approach to allow multiple parameterizations of a given distribution.

## Related Packages

KeywordDispatch.jl is very similar. When we started KeywordCalls, it seemed we would need lots of extra dependencies to make the idea work. This motivated creating a new package instead of making a PR for KeywordDispatch. @simeonschaub helped us get away from this and simplify the implementation; it's now very light-weight, and very fast.