How to use `kwargs` to avoid passing around keyword arguments?

I found the documentation on kwargs to be a little terse… how can I exploit keyword arguments to avoid copying tons of different keyword arguments when passing them function to function?

my example below. seems unnatural to write out so many keyword arguments and keep track of them in two places. or is this what needs done? note _viz_posterior_fit! will be called elsewhere. thx for tips/insights. will pass on to my students :slight_smile:

function _viz_posterior_fit!(ax::Axis, data::DataFrame, bayes_res::NamedTuple;
	                         show_bands::Bool=true, 
						     show_function_samples::Bool=false, 
						     show_unobs_data::Bool=true, 
						     show_model::Bool=true,
						     show_legend::Bool=true)
    # tons of code to modify ax

end
function viz_posterior_fit(data::DataFrame, bayes_res::NamedTuple; 
						   show_bands::Bool=true, 
						   show_function_samples::Bool=false, 
						   show_unobs_data::Bool=true, 
						   show_model::Bool=true,
						   show_legend::Bool=true,
						   savename::Union{Nothing, String}=nothing)
	fig = Figure()
	ax = Axis(fig[1, 1], xlabel="time [min]", ylabel="mass uptake [ng/cm²]")
	_viz_posterior_fit!(ax, data, bayes_res; 
	show_bands=show_bands, show_function_samples=show_function_samples, show_unobs_data=show_unobs_data, show_model=show_model, show_legend=show_legend)
	if ! isnothing(savename)
		save(savename * "_i_obs$(bayes_res.i_obs).pdf", fig)
	end
	return fig
end

If you are only passing the arguments around to the inner function, you can use something like this:

julia> _f(x; a = 1, b = 2) = x + a + b  # inner function, define all parameters explicitly
_f (generic function with 1 method)

julia> f(x; kargs...) = _f(x; kargs...)  # only pass the kargs... over
f (generic function with 1 method)

julia> f(1)
4

julia> f(1; a = 2)
5

With that you can add keyword parameters to your inner function without having to modify the outer interface.

The other alternative, which is also common, is to define a structure with all parameters and pass that instead, like:

julia> Base.@kwdef struct Options
           a::Int = 1
           b::Int = 2
       end
Options

julia> _f(x; opt = Options()) = x + opt.a + opt.b
_f (generic function with 1 method)

julia> f(x; opt=Options()) = _f(x; opt=opt)
f (generic function with 1 method)

julia> f(1)
4

julia> f(1; opt = Options(a=2))
5

In some situations this provides a more explicit and clearly maintainable code, I think.

7 Likes

:heart_eyes: thank you! also can mix kargs with another keyword argument. awesome.

_f(x; a = 1, b = 2) = x + a + b
f(x; c=0.0, kargs...) = _f(x; kargs...) + c
f(1.0, c=3.0) # 7.0
f(1.0) # 4.0
2 Likes