# Making an efficient function for ignoring unsupported kwargs

**URL:** <https://discourse.julialang.org/t/making-an-efficient-function-for-ignoring-unsupported-kwargs/93794>\
**Category:** Performance\
**Tags:** question\
**Created:** [January 30, 2023, 10:13pm UTC](https://discourse.julialang.org/t/making-an-efficient-function-for-ignoring-unsupported-kwargs/93794 "2023-01-30T22:13:21Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![tictaccat](https://avatars.discourse-cdn.com/v4/letter/t/9f8e36/32.png) [@tictaccat](https://discourse.julialang.org/u/tictaccat)\
**Post date:** [January 30, 2023, 10:13pm UTC](https://discourse.julialang.org/t/making-an-efficient-function-for-ignoring-unsupported-kwargs/93794/1 "2023-01-30T22:13:21Z")

</div>

Given a function `f` that may accept some keyword arguments, I want to make a function `g` that accepts any keyword arguments and ignores those that are unsupported by `f`. Below is code that achieves this goal:

```julia
function ignore_unsupported_kwargs(f)
    function g(args...; kwargs...)
        fmethod = which(Tuple{typeof(f), typeof.(args)...})
        accepted_kwargs = Tuple(Base.kwarg_decl(fmethod))
        filtered_kwargs = pairs(kwargs[intersect(accepted_kwargs, keys(kwargs))])
        return f(args...; filtered_kwargs...)
    end
end

z(;x) = x
z2 = ignore_unsupported_kwargs(z)
z2(;x=3,y=4) # works! but much slower than z, allocates
# 0.000043 seconds (30 allocations: 1.688 KiB)

```

However, this code seems to be quite slow: I’d ideally like there to be almost zero overhead. I’ve played around with generated functions to try and move the type-dependent computation out, but I haven’t gotten anything to work. I’d appreciate any help!

---

<div class="post-metadata">

**Author:** ![skleinbo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skleinbo/32/36080_2.png) [@skleinbo](https://discourse.julialang.org/u/skleinbo)\
**Post date:** [January 31, 2023, 8:30am UTC](https://discourse.julialang.org/t/making-an-efficient-function-for-ignoring-unsupported-kwargs/93794/2 "2023-01-31T08:30:58Z")

</div>

Wouldn’t it be easier to declare `f(arg1, arg2,...; kw1, kw2,..., kwargs...)` and simply ignore `kwargs` in the function body?

---

<div class="post-metadata">

**Author:** ![tictaccat](https://avatars.discourse-cdn.com/v4/letter/t/9f8e36/32.png) [@tictaccat](https://discourse.julialang.org/u/tictaccat)\
**Post date:** [January 31, 2023, 8:43am UTC](https://discourse.julialang.org/t/making-an-efficient-function-for-ignoring-unsupported-kwargs/93794/3 "2023-01-31T08:43:17Z")

</div>

Right, but `f` is user-provided and I want to “correct” the signature to drop the `kwargs`. So I would want to automatically take in any `f` and make the approporiate wrapping such as what you wrote.

---

<div class="post-metadata">

**Author:** ![tictaccat](https://avatars.discourse-cdn.com/v4/letter/t/9f8e36/32.png) [@tictaccat](https://discourse.julialang.org/u/tictaccat)\
**Post date:** [January 31, 2023, 10:13am UTC](https://discourse.julialang.org/t/making-an-efficient-function-for-ignoring-unsupported-kwargs/93794/4 "2023-01-31T10:13:40Z")

</div>

I managed to come up with something that doesn’t seem to add much overhead, using `@generated`:

```julia
function _get_kwarg_fields(kwargs_type::Type{Iterators.Pairs{K, V, I, T}}) where {K,V,I,T}
    return fieldnames(T)
end

@generated function _ignore_unsupported_kwargs(f, args...; kwargs...)
    fmethod = which(Tuple{f, args...})
    accepted_kwarg_fields = Base.kwarg_decl(fmethod)
    given_kwarg_fields = _get_kwarg_fields(kwargs)
    if Symbol("kwargs...") in given_kwarg_fields
        return :(f(args...; kwargs...))
    end
    filtered_kwarg_fields = Tuple(intersect(accepted_kwarg_fields, given_kwarg_fields))
    return quote
        filtered_kwarg_values = map(Base.Fix1(Base.getindex, kwargs), $filtered_kwarg_fields)
        filtered_kwargs = NamedTuple{$filtered_kwarg_fields}(filtered_kwarg_values)
        return f(args...; filtered_kwargs...)
    end
end

function ignore_unsupported_kwargs(f)
    return (args...; kwargs...) -> _ignore_unsupported_kwargs(f, args...; kwargs...)
end

```

Let me know if you have any thoughts! An example usage is:

```julia
julia> f(; x, y) = x + y
f (generic function with 1 method)

julia> f(a::Int; b, c) = a + b + c
f (generic function with 2 methods)

julia> f2 = ignore_unsupported_kwargs(f)
#5 (generic function with 1 method)

julia> f2(; x=5, y=7, z=10)
12

julia> f2(3; b=4, c=10, d=12)
17

```

---

<div class="post-metadata">

**Author:** ![tictaccat](https://avatars.discourse-cdn.com/v4/letter/t/9f8e36/32.png) [@tictaccat](https://discourse.julialang.org/u/tictaccat)\
**Post date:** [January 31, 2023, 4:45pm UTC](https://discourse.julialang.org/t/making-an-efficient-function-for-ignoring-unsupported-kwargs/93794/5 "2023-01-31T16:45:59Z")

</div>

From what I’ve read online, the use of `which` in the generated function is not ideal since it depends on the global method table which may change over time. I haven’t been able to find any cases where there are any issues with the above, but I’d appreciate any help with writing an implementation of this functionality that does not violate any assumptions for generated functions.
