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.

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.

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().

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.

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.

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

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

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?

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.

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")

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"

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 ?