Pass function arguments in tuple, how to manage keyword arguments

#1

I have a function with some optional keyword arguments.

function f1(a::Int, b::Float64; c::Int=42, d::Int=43)

Another top level function may sometimes call f1, but I don’t want to bother the user with specifying f1's arguments if they’re not necessary. And when the arguments are required, I want to make it as easy to manage as possible.
This is my partial solution so far

function f_top(call_f1::Bool; f1_params::Union{Tuple,Nothing}=nothing)
    if call_f1
        isnothing(f1_params) && throw(ArgumentError)
        f1(f1_params...)
    end
end

So this works

f1_params = (1, 2.0)
f_top(true, f1_params=f1_params)

But what if I want to specify c and/or d? Doesn’t seem possible using this approach. Is there a more idiomatic solution to this type of problem?

(This is obviously a MWE and in my real problem f1 has around 20 parameters. It’s actually a constructor for a struct).

#2

How about

function f_top(call_f1::Bool; f1_params::Union{Tuple,Nothing}=nothing, f2_kwargs...)
    if call_f1
        isnothing(f1_params) && throw(ArgumentError)
        f1(f1_params...; f2_kwargs...)
    end
end

with f1(a::Int, b::Float64; c::Int=42, d::Int=43) = a+b+c+d

julia> f_top(true, f1_params=(1,2.0), c=3)
49.0
#3

For many keyword arguments that are passed around/downstream this way, it is common to wrap them in a struct defined for the purpose. Base.@kwdef provides a nice interface for construction.

1 Like
#4

Beautiful, Base.@kwdef is perfect! Thanks.

My focus here is to develop the nicest possible interface, so that my reluctant colleagues have no excuses not to start using julia.