# Smart kwargs... dispatch

**URL:** <https://discourse.julialang.org/t/smart-kwargs-dispatch/14571>\
**Category:** New to Julia\
**Tags:** kwargs\
**Created:** [September 5, 2018, 8:54am UTC](https://discourse.julialang.org/t/smart-kwargs-dispatch/14571 "2018-09-05T08:54:39Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![DominiqueMakowski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dominiquemakowski/32/51410_2.png) [@DominiqueMakowski](https://discourse.julialang.org/u/DominiqueMakowski)\
**Post date:** [September 5, 2018, 8:54am UTC](https://discourse.julialang.org/t/smart-kwargs-dispatch/14571/1 "2018-09-05T08:54:39Z")

</div>

Let’s say a function `f()` involves another function with multiple arguments. From what I understood, one can avoid listing them with with the `kwargs...` argument that “passes” the optional arguments down to the other functions.

```julia
function f(x; kwargs...)
   g(x; kwargs...)
end

```

Is it possible to setup something similar but when two functions are involved, and smartly dispatch appropriate arguments to each function.

```julia
function f(x; kwargs...)
   y = g(x; kwargs...)
   z = h(y; kwargs...)
end

```

Currently, it would throw a MethodError as some of the kwargs of `g()` do not exist for `h()`.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [September 5, 2018, 9:18am UTC](https://discourse.julialang.org/t/smart-kwargs-dispatch/14571/2 "2018-09-05T09:18:56Z")

</div>

This is a typical idiom in R, but I would avoid it in Julia. Instead, I would prefer

```julia
function f(x, args)
   y = g(x, args)
   z = h(y, args)
end

```

and make `args` a `NamedTuple`.

`g` and `h` can then pick the fields they like. Also see [`Parameters.@unpack`](https://github.com/mauro3/Parameters.jl).

When the interface stabilizes, you can collect the args in a `struct`, without changing `f`, `g`, or `h` fundamentally.

---

<div class="post-metadata">

**Author:** ![korsbo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/korsbo/32/15942_2.png) [@korsbo](https://discourse.julialang.org/u/korsbo)\
**Post date:** [September 5, 2018, 10:18am UTC](https://discourse.julialang.org/t/smart-kwargs-dispatch/14571/3 "2018-09-05T10:18:25Z")

</div>

I can’t say if it is advisable, but it is possible. All you need to do is to slurp the extra kwargs in `g` and `h` as well.

```julia
function f(x; kwargs...)
   y = g(x; kwargs...)
   z = h(y; kwargs...)
end

g(x; g_kwarg="hello", kwargs...) = <some function>
h(x; y_kwarg=:goodbye, kwargs...) = <some other function>

```

This way, you don’t get any method errors. On the other hand, it will no longer warn you if you pass a misspelt kwarg.

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [September 5, 2018, 3:05pm UTC](https://discourse.julialang.org/t/smart-kwargs-dispatch/14571/4 "2018-09-05T15:05:28Z")

</div>

> [@Tamas\_Papp](#):
>
> and make `args` a `NamedTuple` .

The problem with this is that you cannot build in defaults into the `args` field, right? On the other hand @korsbo approach has pretty low overhead

```julia
julia> @noinline f1(;x::Int = 1, kwargs...) = x; @noinline f2(;y::Int = 2, kwargs...) = y;

julia> f(; kwargs...) = f1(;kwargs...) + f2(;kwargs...)
f (generic function with 1 method)

julia> @btime f()
  0.026 ns (0 allocations: 0 bytes)
3

julia> @btime f(x=4)
  17.066 ns (1 allocation: 32 bytes)
6

```

---

<div class="post-metadata">

**Author:** ![piever](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/piever/32/1815_2.png) [@piever](https://discourse.julialang.org/u/piever)\
**Post date:** [September 5, 2018, 3:33pm UTC](https://discourse.julialang.org/t/smart-kwargs-dispatch/14571/5 "2018-09-05T15:33:07Z")

</div>

If you know in advance what are the keywords that `f` accepts you could also do something like:

```julia
function f(x; kwargs...)
   belongstog(s) = first(s) in v # where v are the keywords that f accepts
   kw1 = filter(belongstog, kwargs)
   kw2 = filter(!belongstog, kwargs)
   y = g(x; kw1...)
   z = h(y; kw2...)
end

```

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [September 7, 2018, 5:47pm UTC](https://discourse.julialang.org/t/smart-kwargs-dispatch/14571/6 "2018-09-07T17:47:11Z")

</div>

That’s reminiscent of Mathematica’s approach. But in Mathematica we have `Options[function]`, which returns the kwargs in `function`. Does anybody know if there a way to obtain the kwargs admitted by a function (the `v` in @piever’s code) by introspection, somehow?

---

<div class="post-metadata">

**Author:** ![BeastyBlacksmith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/beastyblacksmith/32/4741_2.png) [@BeastyBlacksmith](https://discourse.julialang.org/u/BeastyBlacksmith)\
**Post date:** [November 6, 2018, 11:35am UTC](https://discourse.julialang.org/t/smart-kwargs-dispatch/14571/7 "2018-11-06T11:35:50Z")

</div>

I was wondering if a syntax like `f( args; kwargs1... ;kwargs2... ; ... ) `  
would make sense for this, then one could define

```julia
function f(; kwargs1... ; kwargs2... )
  g( ;kwargs1... )
  h( ;kwargs2... )
end

```

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [November 6, 2018, 2:37pm UTC](https://discourse.julialang.org/t/smart-kwargs-dispatch/14571/8 "2018-11-06T14:37:01Z")

</div>

Calling `f(; a = 1, b = 2, c = 3)` what is `kwargs1` and `kwargs2`?.

---

<div class="post-metadata">

**Author:** ![BeastyBlacksmith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/beastyblacksmith/32/4741_2.png) [@BeastyBlacksmith](https://discourse.julialang.org/u/BeastyBlacksmith)\
**Post date:** [November 6, 2018, 3:05pm UTC](https://discourse.julialang.org/t/smart-kwargs-dispatch/14571/9 "2018-11-06T15:05:28Z")

</div>

Well calling would have to be `f(; a = 1, b = 2; c = 3 )` also.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [November 6, 2018, 3:34pm UTC](https://discourse.julialang.org/t/smart-kwargs-dispatch/14571/10 "2018-11-06T15:34:16Z")

</div>

What is the use case?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [November 6, 2018, 3:36pm UTC](https://discourse.julialang.org/t/smart-kwargs-dispatch/14571/11 "2018-11-06T15:36:39Z")

</div>

> [@BeastyBlacksmith](#):
>
> Well calling would have to be `f(; a = 1, b = 2; c = 3 )` also.

Now it leaks out to the caller though while it seems like the usecase for this should just be a convenience for the function itself.

---

<div class="post-metadata">

**Author:** ![BeastyBlacksmith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/beastyblacksmith/32/4741_2.png) [@BeastyBlacksmith](https://discourse.julialang.org/u/BeastyBlacksmith)\
**Post date:** [November 6, 2018, 3:38pm UTC](https://discourse.julialang.org/t/smart-kwargs-dispatch/14571/12 "2018-11-06T15:38:28Z")

</div>

For example writing a function that calls an optimization routine, as well as an ODE solve and a plotting routine which may share same keyword arguments, then one could pass the keywords to those separately.  
But maybe namedtuples is a better approach in this case anyways.

---

<div class="post-metadata">

**Author:** ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)\
**Post date:** [November 6, 2018, 3:53pm UTC](https://discourse.julialang.org/t/smart-kwargs-dispatch/14571/13 "2018-11-06T15:53:55Z")

</div>

you can have defaults with a namedtuple

```julia
julia> function f(nt::NamedTuple{(:a,:b,:c)}=(a=1, b=2.0, c="three"))
          return nt
       end
f (generic function with 2 methods)

julia> f((a=2, b=3.0, c="four"))
(a = 2, b = 3.0, c = "four")

julia> f()
(a = 1, b = 2.0, c = "three")

```

---

<div class="post-metadata">

**Author:** ![cscherrer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cscherrer/32/7631_2.png) [@cscherrer](https://discourse.julialang.org/u/cscherrer)\
**Post date:** [April 22, 2019, 6:53pm UTC](https://discourse.julialang.org/t/smart-kwargs-dispatch/14571/14 "2019-04-22T18:53:06Z")

</div>

I’ve been doing it something like this:

```julia
julia> function foo(;kwargs...)
           kwargs = Dict(kwargs)
           x = get(kwargs, :x, "default")
           return x
       end
foo (generic function with 1 method)

julia> foo(x="myValue")
"myValue"

julia> foo()
"default"

```

---

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [April 22, 2019, 8:08pm UTC](https://discourse.julialang.org/t/smart-kwargs-dispatch/14571/15 "2019-04-22T20:08:40Z")

</div>

the following would be faster, and is a general pattern.

```julia
function foo(;kwargs...)
       defaults = (; x="default")
       settings = merge(defaults, kwargs)
       x = settings.x
       return x
end

```

merge of two namestuples is extremely fast.

---

<div class="post-metadata">

**Author:** ![alejandrovpm](https://avatars.discourse-cdn.com/v4/letter/a/3be4f8/32.png) [@alejandrovpm](https://discourse.julialang.org/u/alejandrovpm)\
**Post date:** [March 30, 2020, 11:45am UTC](https://discourse.julialang.org/t/smart-kwargs-dispatch/14571/16 "2020-03-30T11:45:40Z")

</div>

Hello,

I upgraded from version 0.63 to version 1.4 and when I try to merge the default and new kwargs it throws the following error message:  
MethodError: no method matching merge!(::NamedTuple{(:x,),Tuple{String}}, ::Base.Iterators.Pairs{Symbol,String,Tuple{Symbol},NamedTuple{(:x,),Tuple{String}}})

I suppose, that merge is not defined for the this type of variable. Do you suggest a way to do it ?

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [March 30, 2020, 2:37pm UTC](https://discourse.julialang.org/t/smart-kwargs-dispatch/14571/17 "2020-03-30T14:37:32Z")

</div>

Welcome, @alejandrovpm!

We’re happy to help, but please open a new topic for this rather than posting on an old thread.
