# Specializing on keyword arguments

**URL:** <https://discourse.julialang.org/t/specializing-on-keyword-arguments/78263>\
**Category:** General Usage\
**Tags:** argument, keywords\
**Created:** [March 22, 2022, 9:46am UTC](https://discourse.julialang.org/t/specializing-on-keyword-arguments/78263 "2022-03-22T09:46:38Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![etienne\_dg](https://avatars.discourse-cdn.com/v4/letter/e/fbc32d/32.png) [@etienne\_dg](https://discourse.julialang.org/u/etienne_dg)\
**Post date:** [March 22, 2022, 9:46am UTC](https://discourse.julialang.org/t/specializing-on-keyword-arguments/78263/1 "2022-03-22T09:46:38Z")

</div>

I have a function `f(a; b=default_b, c=default_c)`, and want to implement a method `f(a) = f(a, b=default_b, c=c_specialized_for_default_b)`, which should override `f` when neither `b` and `c` are provided. If I implement it like this, Julia does not choose the second method, but return `Method definition overwritten` (which is kinda expected, although we could hope Julia choose the latter one when calling `f(a)` by some dispatch-like reasoning).  
I can implement it like this:

```julia
f(a; b=default_b, c=default_c)
    if b == default_b && c == default_c
        c = c_specialized_for_default_b
    end
    # some code
end

```

Is there a cleaner way (and maybe more efficient) to do this? Maybe there is a way to check if arguments are provided ?

---

<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:** [March 22, 2022, 12:14pm UTC](https://discourse.julialang.org/t/specializing-on-keyword-arguments/78263/2 "2022-03-22T12:14:54Z")

</div>

I would use something like this, probably:

```julia
julia> function f(a; b=nothing, c=nothing)
           if isnothing(b) && isnothing(c)
               return _f(a)
           else
               return _f(a,b,c)
           end
       end
           
f (generic function with 1 method)

```

where `_f(...)` is the internal function for which the one with keyword arguments is the exposed interface.

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [March 22, 2022, 12:19pm UTC](https://discourse.julialang.org/t/specializing-on-keyword-arguments/78263/3 "2022-03-22T12:19:10Z")

</div>

As you noted keyword arguments don’t take part in dispatch, so you need to use some other mechanism. The primary options I know are

1. Do it Python-style with `f(a; b = nothing, c = nothing)` and do `isnothing` checks to fill in desired defaults. This may have some type stability issues so it’s usually a good idea to have a function barrier before doing actual computations (i.e. call a new function or a different method of the same function).
2. Define your function as `f(a; kwargs...)` and introspect `kwargs` to decide how to proceed with the call.

For the second option your example could be

```julia
function _f(a; b = default_b, c = default_c)
    # some code
end

f(a; kwargs...) = isempty(kwargs) ? _f(a; c = c_specialized_for_default_b) : _f(a; kwargs...)

```

For an example of complex keyword argument handling you can trace your way through this function: [https://github.com/GunnarFarneback/LongestPaths.jl/blob/debd52b7bcaf59ceefac1d48935fbd8359dafb5b/src/longest\_path.jl#L242](https://github.com/GunnarFarneback/LongestPaths.jl/blob/debd52b7bcaf59ceefac1d48935fbd8359dafb5b/src/longest_path.jl#L242)

---

<div class="post-metadata">

**Author:** ![etienne\_dg](https://avatars.discourse-cdn.com/v4/letter/e/fbc32d/32.png) [@etienne\_dg](https://discourse.julialang.org/u/etienne_dg)\
**Post date:** [March 22, 2022, 1:13pm UTC](https://discourse.julialang.org/t/specializing-on-keyword-arguments/78263/4 "2022-03-22T13:13:34Z")

</div>

Ok, thanks for your replies. So if I understand correctly, I need to change the definition of `f(a::Type1; b::Type2=default_b, c::Type3=default_c)` to `f(a::Type1; b::Union{Nothing, Type2}=nothing, c::Union{Nothing, Type3}=nothing)` (with the arguments management to call internal function that go with it) and there will be no breaking changes, am I correct ?

---

<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:** [March 22, 2022, 1:15pm UTC](https://discourse.julialang.org/t/specializing-on-keyword-arguments/78263/5 "2022-03-22T13:15:52Z")

</div>

No need to be specific about the types, just use

```julia
f(a::Type1; b=nothing, c=nothing)

```

(unless there is a good reason to specify that further - performance is not affected by that).

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [March 22, 2022, 2:30pm UTC](https://discourse.julialang.org/t/specializing-on-keyword-arguments/78263/6 "2022-03-22T14:30:43Z")

</div>

I think if your objective is just to change the default value of `c` when `b` has the default value then your original solution may be the best. Note that just because Julia does not dispatch on keyword arguments it does not mean it cannot specialize on them, if performance is what you are worried about.

---

<div class="post-metadata">

**Author:** ![etienne\_dg](https://avatars.discourse-cdn.com/v4/letter/e/fbc32d/32.png) [@etienne\_dg](https://discourse.julialang.org/u/etienne_dg)\
**Post date:** [March 22, 2022, 2:41pm UTC](https://discourse.julialang.org/t/specializing-on-keyword-arguments/78263/7 "2022-03-22T14:41:11Z")

</div>

My concern about performance was in the comparison on arguments to check if they are defaults, which could be costly if the objects are huge. Using `nothing` solves this, but this is not critical in my problem.

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [March 22, 2022, 2:44pm UTC](https://discourse.julialang.org/t/specializing-on-keyword-arguments/78263/8 "2022-03-22T14:44:37Z")

</div>

Ah, yes, in that case the solution with `nothing` has a clear advantage.
