# How to customize broadcast for a function that accepts keyword arguments?

**URL:** <https://discourse.julialang.org/t/how-to-customize-broadcast-for-a-function-that-accepts-keyword-arguments/86351>\
**Category:** General Usage\
**Tags:** question, broadcast, function\
**Created:** [August 25, 2022, 5:28pm UTC](https://discourse.julialang.org/t/how-to-customize-broadcast-for-a-function-that-accepts-keyword-arguments/86351 "2022-08-25T17:28:47Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [August 25, 2022, 5:28pm UTC](https://discourse.julialang.org/t/how-to-customize-broadcast-for-a-function-that-accepts-keyword-arguments/86351/1 "2022-08-25T17:28:47Z")

</div>

Suppose I have a function

```julia
julia> function f(n::Int)
           @assert n > 0
           n == 1 && return 1
           f(n-1) + 1
       end

```

and another function to cache the values of `f(n)` for a range of `n`:

```julia
julia> cachef(nr) = collect(nr)

```

Performance wise, broadcasting `f` over a range of `n` is much slower than calling `cachef`

```julia
julia> @btime cachef(1:1_000);
  736.652 ns (1 allocation: 7.94 KiB)

julia> @btime f.(1:1_000);
  4.881 ms (1 allocation: 7.94 KiB)

```

In this case, I may customize the broadcasting behavior of `f` as

```julia
julia> function Base.copy(B::Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1}, Tuple{Base.OneTo{Int64}}, typeof(f), Tuple{UnitRange{Int64}}})
           nr, = B.args
           cachef(nr)
       end

```

With this defined, I obtain

```julia
julia> @btime f.(1:1_000);
  721.657 ns (1 allocation: 7.94 KiB)

```

This shows that broadcasting now uses `cachef`. This works for functions that only accept positional arguments. How does one generalize this to functions that accept keyword arguments?

For example

```julia
julia> g(n; a=nothing) = f(n);

julia> @btime g.(1:1000, a=nothing);
  4.874 ms (1 allocation: 7.94 KiB)

```

So, this doesn’t inherit the broadcasting performance of `f`, which is unfortunate. Looking into the code generated:

```julia
julia> Meta.@lower g.(1:1000, a=nothing)
:($(Expr(:thunk, CodeInfo(
    @ none within `top-level scope`
1 ─ %1 = 1:1000
│ %2 = Base.broadcasted_kwsyntax
│ %3 = Core.tuple(:a)
│ %4 = Core.apply_type(Core.NamedTuple, %3)
│ %5 = Core.tuple(nothing)
│ %6 = (%4)(%5)
│ %7 = Core.kwfunc(%2)
│ %8 = (%7)(%6, %2, g, %1)
│ %9 = Base.materialize(%8)
└── return %9
))))

```

Is `Core.kwfunc` returning an anonymous function here? Can one specialize broadcast for such a function? Given that none of this is documented, I am wary of using this, but then how does one specialize broadcast for a function that accepts keyword arguments?
