Extracting kwargs from anonymous function

Here’s how I would do this:

using ExprTools: splitdef
struct ParametricFunction{N,M,F}
    f::F
    params::NTuple{M,Symbol}
end

ParametricFunction{N}(f::F, p::NTuple{M,Symbol}) where {N,M,F} = ParametricFunction{N,M,F}(f, p)

(pf::ParametricFunction)(args...; kw...) = pf.f(args...; kw...)

parameters(p::ParametricFunction) = p.params


macro par(f::Expr)
    (f.head == :->) || throw(ArgumentError("Only @par(args -> ..., parameters...) syntax supported"))
    d = splitdef(f)
    kwargs = get!(d, :kwargs, []) #use get! because the :kwargs might not exist
    params = (x -> x isa Symbol ? x : x.args[1]).(kwargs) |> Tuple
    N = length(get!(d, :args, []))
    esc(:(ParametricFunction{$N}($f, $params)))
end

and then


julia> @macroexpand @par (x, y; a) -> x * y * a
 :(ParametricFunction{2}(((x, y; a)->begin
               #= In[90]:38 =#
               x * y * a
           end), (:a,)))

julia> pf = @par (x, y; a) -> x * y * a
ParametricFunction{2,1,var"#74#76"}(var"#74#76"(), (:a,))

julia> parameters(pf)
(a,)

julia> pf(1, 2, a=3)
6

To be clear, there’s nothing wrong with the syntax you’re using, I just personally find it easier to understand the kwarg syntax.

2 Likes