Save kwargs in struct field to be used later in function calls

I have a struct Foo with a field that contains keyword arguments given at construction. I want to then be able to call a function with keyword arguments recovered from Foo:

struct Foo
    kwargs
end

Foo(;kwargs...) = Foo(kwargs)

f(; kwargs...) = nothing

g(foo::Foo) = f(foo.kwargs)

julia> foo = Foo(a = 1, b = 2)
Foo(Base.Iterators.Pairs(:a => 1,:b => 2))

julia> g(foo)
ERROR: MethodError: no method matching f(::Base.Iterators.Pairs{Symbol,Int64,Tuple{Symbol,Symbol},NamedTuple{(:a, :b),Tuple{Int64,Int64}}})
Closest candidates are:
  f(; kwargs...) at none:1
Stacktrace:
 [1] g(::Foo) at .\none:1
 [2] top-level scope at none:0


I have tried different approaches but none worked. Notably using Foo(;kwargs...) = Foo(values(kwargs)) to save a NamedTuple instead of a a Iterators.pairs. Is there some way to make this work or am I trying to do something that doesn’t make sense ?

you want to splice it in as

f(; foo.kwargs...)

(incidentally, see the “closest candidates” error message).

Ha okay, what I had tried in that same idea was

julia> g(foo::Foo) = f(foo.kwargs...)
g (generic function with 3 methods)

julia> g(foo)
ERROR: MethodError: no method matching f(::Pair{Symbol,Int64}, ::Pair{Symbol,Int64})
Stacktrace:
 [1] g(::Foo) at .\none:1
 [2] top-level scope at none:0

without the ;. I did not know that the semi colon was used in funcion calls, I thought it was only in definitions. But yes it makes sense since it is trying to use the Iterator as varargs. Thank you.

The role of ; is to separate the keyword and the positional arguments. Splatting keyword arguments is documented in this section:

https://docs.julialang.org/en/v1/manual/functions/#Keyword-Arguments-1