Add varargs... to generic function

Is there a function that can take any kwargs function and return the same function with a varargs… parameter? That is

convert
f(; a ) = 1
to
f(; a, X... ) = 1

and
f(; a,b,c ) = a+b+c
to
f(; a,b,c, X... ) = a+b+c

That’s a job for a macro. First see how the function expressions look without and with a varargs argument.

julia> dump(:(f(; a) = 1))
Expr
  head: Symbol =
  args: Array{Any}((2,))
    1: Expr
      head: Symbol call
      args: Array{Any}((2,))
        1: Symbol f
        2: Expr
          head: Symbol parameters
          args: Array{Any}((1,))
            1: Symbol a
    2: Expr
      head: Symbol block
      args: Array{Any}((2,))
        1: LineNumberNode
          line: Int64 1
          file: Symbol REPL[1]
        2: Int64 1

julia> dump(:(f(; a, _...) = 1))
Expr
  head: Symbol =
  args: Array{Any}((2,))
    1: Expr
      head: Symbol call
      args: Array{Any}((2,))
        1: Symbol f
        2: Expr
          head: Symbol parameters
          args: Array{Any}((2,))
            1: Symbol a
            2: Expr                   # Here is the vararg.
              head: Symbol ...
              args: Array{Any}((1,))
                1: Symbol _
    2: Expr
      head: Symbol block
      args: Array{Any}((2,))
        1: LineNumberNode
          line: Int64 1
          file: Symbol REPL[2]
        2: Int64 1

Now we need to transform the former to the latter.

macro ignore_extra_kwargs(ex)
    push!(ex.args[1].args[2].args, :(_...))
    return esc(ex)
end

Here it is in action:

julia> @macroexpand @ignore_extra_kwargs f(; a ) = 1
:(f(; a, _...) = begin
          #= REPL[4]:1 =#
          1
      end)

julia> @ignore_extra_kwargs f(; a ) = 1
f (generic function with 1 method)

julia> f(a = 1, b = 2)
1
4 Likes

Sorry to be stupid. How come this doesn’t work?

f(; a ) = 1

@ignore_extra_kwargs f

The macro transforms the code which defines f, it doesn’t act on the function.