# How can kwargs be used in multiple dispatch

**URL:** https://discourse.julialang.org/t/how-can-kwargs-be-used-in-multiple-dispatch/86790
**Category:** General Usage
**Tags:** question
**Created:** [September 5, 2022, 9:05am UTC](https://discourse.julialang.org/t/how-can-kwargs-be-used-in-multiple-dispatch/86790 "2022-09-05T09:05:12Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![this\_josh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/this_josh/32/42679_2.png) [@this\_josh](https://discourse.julialang.org/u/this_josh)
#### Post date: [September 5, 2022, 9:05am UTC](https://discourse.julialang.org/t/how-can-kwargs-be-used-in-multiple-dispatch/86790/1 "2022-09-05T09:05:12Z")

</div>

Multiple dispatch usually works on variable types, I presumed it could also work using kwargs, but it doesn’t seem to. How can I make this work?

```nohighlight
julia> function shout(word::String; exclaim::Int)
           println(word * "!"^exclaim)
       end
shout (generic function with 1 method)

julia> function shout(word::String; question::Real)
           println(word * "?"^question)
       end
shout (generic function with 1 method)

julia> shout("Hello", exclaim=3)
ERROR: UndefKeywordError: keyword argument question not assigned
Stacktrace:
 [1] top-level scope
   @ REPL[3]:1

julia> shout("Hello", question=3)
Hello???

```

I’m guessing the problem here is that an Int is a subset of Real, so calling `shout(String, Int)` is applicable to both methods.

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [September 5, 2022, 9:24am UTC](https://discourse.julialang.org/t/how-can-kwargs-be-used-in-multiple-dispatch/86790/2 "2022-09-05T09:24:06Z")

</div>

Kwargs do not differentiate methods, so the Int version was overwritten (note the `1 method` after the second definition).

I use this approach, in cases like this:

```julia
_f(a, b::Int) = 1
_f(a, c::Real) = 2
function f(a; b = nothing, c = nothing)
    !isnothing(b) && return _f(a,b)
    !isnothing(c) && return _f(a,c)
end

```

But I’m not a fan of it. Other opinions are welcome.

---

<div class="post-metadata">

### Author: ![this\_josh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/this_josh/32/42679_2.png) [@this\_josh](https://discourse.julialang.org/u/this_josh)
#### Post date: [September 5, 2022, 9:30am UTC](https://discourse.julialang.org/t/how-can-kwargs-be-used-in-multiple-dispatch/86790/3 "2022-09-05T09:30:20Z")

</div>

Thank you for your solution, I can see how it works but as you suggest it is possibly not the best. I won’t accept it as a solution yet in case someone has a more elegant one we can both benefit from.

---

<div class="post-metadata">

### Author: ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)
#### Post date: [September 5, 2022, 10:36am UTC](https://discourse.julialang.org/t/how-can-kwargs-be-used-in-multiple-dispatch/86790/4 "2022-09-05T10:36:22Z")

</div>

Another option is to use the package [KeywordDispatch](https://github.com/simonbyrne/KeywordDispatch.jl).jl.

---

<div class="post-metadata">

### Author: ![\_bernhard](https://avatars.discourse-cdn.com/v4/letter/_/bc79bd/32.png) [@\_bernhard](https://discourse.julialang.org/u/_bernhard)
#### Post date: [September 5, 2022, 10:36am UTC](https://discourse.julialang.org/t/how-can-kwargs-be-used-in-multiple-dispatch/86790/5 "2022-09-05T10:36:26Z")

</div>

If the example that you supplied is close to your actual usecase, the following appraoch would work:

```julia
julia> function shout(word::String, exclaim::Int)
           println(word * "!"^exclaim)
       end
shout (generic function with 1 method)

julia> function shout(word::String, question::Real)
           println(word * "?"^question)
       end
shout (generic function with 2 methods)

julia> function shout(word::String; kwargs...)
           return shout(word, last(only(kwargs)))
       end
shout (generic function with 3 methods)

```

Note, that in the first two methods, the second argument is not a keyword argument, but positional and thus dispatch works as expected.  
The last method can take any keyword argument and simply passes its value on to either of the two other methods.

EDIT: If, however, you have more than one keyword argument you would need an intermediate step, that passes the arguments on in the correct order.

EDIT2: Unfortunately, this still does not work, as the `question`-method needs an `Integer` to work, but then it is dispatched to the `exlaim`-method. It is generally bad practice to suggest via the method signature, that the method would work with any `Real`, when it actually requires an `Integer`.  
But if the two types `Real` and `Integer` where not related, this way would work.

EDIT3: The easiest way to solve your problem (although maybe not how you intended) would simply be:

```julia
julia> function shout(word::String; exclaim=0, question=0)
           println(word * "?"^question * "!"^exclaim)
       end
shout (generic function with 3 methods)

```

---

<div class="post-metadata">

### Author: ![this\_josh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/this_josh/32/42679_2.png) [@this\_josh](https://discourse.julialang.org/u/this_josh)
#### Post date: [September 5, 2022, 12:16pm UTC](https://discourse.julialang.org/t/how-can-kwargs-be-used-in-multiple-dispatch/86790/6 "2022-09-05T12:16:10Z")

</div>

Again, thank you for your solution, I think it is still rather complex as highlighted with edits one and two.

You have successfully dissected my MRE to a point where it doesn’t replicate my actual problem which is fun to see 🙂 Unfortunately, my actual use case requires `Int` and `Real`.

Edit 3 is interesting, it would be a more pythonic/ditch multiple dispatch approach which would work too. I’d have to have an if statement though, so it’d be more like

```nohighlight
function shout(word::String; exclaim::Union{Nothing, Int}=nothing, question::Union{Nothing, Int} =nothing )
    if exclaim === nothing && question === nothing
        error("Only one of exclaim or question can be specified")
    elseif !isnothing(exclaim)
        println(word * "!"^exclaim)
    elseif !isnothing(question)
        println(word * "?"^question)
    else
        error("One of exclaim or question must be specified")
    end
end

```

Although this would be its most verbose form, if after refactoring it would lose the beauty of multiple-dispatch.

---

<div class="post-metadata">

### Author: ![this\_josh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/this_josh/32/42679_2.png) [@this\_josh](https://discourse.julialang.org/u/this_josh)
#### Post date: [September 5, 2022, 12:29pm UTC](https://discourse.julialang.org/t/how-can-kwargs-be-used-in-multiple-dispatch/86790/7 "2022-09-05T12:29:11Z")

</div>

Thank you for linking this package, I wasn’t aware of it. It should be perfect but I cannot get it to work as desired, **I get the same error as in the initial example**

```nohighlight
julia> @kwdispatch shout()
julia> function shout(word::String; exclaim::Int)
                  println(word * "!"^exclaim)
              end
shout (generic function with 2 methods)
julia> function shout(word::String; question::Real)
                  println(word * "?"^question)
              end
shout (generic function with 2 methods)
julia> shout("Hello", exclaim=3)
ERROR: UndefKeywordError: keyword argument question not assigned
Stacktrace:
 [1] top-level scope
   @ REPL[34]:1
julia> shout("Hello", question=3)
Hello???

```

I have also tried `@kwdispatch shout(word::String)` in case the common argument is required. In the examples given they only seem to have kwargs, so I’m not sure if there is a problem having positional and keyword?

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [September 5, 2022, 12:41pm UTC](https://discourse.julialang.org/t/how-can-kwargs-be-used-in-multiple-dispatch/86790/8 "2022-09-05T12:41:51Z")

</div>

The way to sort of use multiple dispatch here is to do this:

```julia
julia> _shout(word::String, exclaim::Int, question::Nothing) = println(word * "!"^exclaim)
_shout (generic function with 1 method)

julia> _shout(word::String, exclaim::Nothing, question::Int) = println(word * "?"^question)
_shout (generic function with 2 methods)

julia> _shout(word::String, exclaim::Int, question::Int) = error("Only one of exclaim or question can be specified")
_shout (generic function with 3 methods)

julia> shout(word::String; exclaim=nothing, question=nothing) = _shout(word, exclaim, question)
shout (generic function with 1 method)

julia> shout("hello"; exclaim=1)
hello!

julia> shout("hello"; question=1)
hello?

```

But I am not sure if that is cleaner than the simple branches. I opted for the branches last time I had to do that.

---

<div class="post-metadata">

### Author: ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)
#### Post date: [September 5, 2022, 12:59pm UTC](https://discourse.julialang.org/t/how-can-kwargs-be-used-in-multiple-dispatch/86790/9 "2022-09-05T12:59:23Z")

</div>

That is strange. The following code works for me:

```julia
 using KeywordDispatch

 @kwdispatch shout(word::String)

 @kwmethod function shout(word::String; exclaim::Int)
    println(word * "!"^exclaim)
end

@kwmethod function shout(word::String; question::Real)
    println(word * "?"^question)
end

shout("Hello", exclaim=3)

shout("Hello", question=3)

```

I’m using Julia 1.8.0.

---

<div class="post-metadata">

### Author: ![\_bernhard](https://avatars.discourse-cdn.com/v4/letter/_/bc79bd/32.png) [@\_bernhard](https://discourse.julialang.org/u/_bernhard)
#### Post date: [September 5, 2022, 1:04pm UTC](https://discourse.julialang.org/t/how-can-kwargs-be-used-in-multiple-dispatch/86790/10 "2022-09-05T13:04:15Z")

</div>

I guess, in principle, EDIT2 would be the right way for your requirement. The only problem is, that `exclaim` method takes an `Int` and the `question`-method a `Real` (i.e. the supertype of both `Integer` and `AbstractFloat`). This means, that via normal dispatch you’re only able to reach the `question`-method if the argument is not `<:Integer` (which probably is the reason, that you are reaching for keyword arguments in the first place).  
That said, one way to get around this is with value types, that allow you to dispatch on values, rather than types:

```julia
julia> function shout(word::String; kwargs...)
           key,value = only(kwargs)
           shout(word, value, Val{key}())
end
shout (generic function with 1 method)

julia> function shout(word::String, question::Real, ::Val{:question})
                  println(word * "?"^question)
end
shout (generic function with 2 methods)

julia> function shout(word::String, exclaim::Int, ::Val{:exclaim})
                  println(word * "!"^exclaim)
end
shout (generic function with 3 methods)

```

---

<div class="post-metadata">

### Author: ![this\_josh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/this_josh/32/42679_2.png) [@this\_josh](https://discourse.julialang.org/u/this_josh)
#### Post date: [September 5, 2022, 1:13pm UTC](https://discourse.julialang.org/t/how-can-kwargs-be-used-in-multiple-dispatch/86790/11 "2022-09-05T13:13:07Z")

</div>

I have this working now, when including the positional arg in `@kwdispatch` I was forgetting to use `@kwmethod`. It is unfortunate that `KeywordDispatch` [cannot have default arguments](https://github.com/simonbyrne/KeywordDispatch.jl/pull/8) though as my real use case would benefit from this. But that wasn’t the original question, thank you for your solution

---

<div class="post-metadata">

### Author: ![this\_josh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/this_josh/32/42679_2.png) [@this\_josh](https://discourse.julialang.org/u/this_josh)
#### Post date: [September 5, 2022, 1:17pm UTC](https://discourse.julialang.org/t/how-can-kwargs-be-used-in-multiple-dispatch/86790/12 "2022-09-05T13:17:19Z")

</div>

Thank you for all your solutions, I need to think about what suits my application best as some of these options are less intuitive than regular multiple dispatch. For code clarity it might be best to have two distinct functions.
