What is interaction between F.() broadcasting and keyword args?

How does F.(a, b; c=d) work with respect to broadcasting? I understand that the arguments a, b will be broadcast. What about the keyword argument?

3 Likes

F.(a, b; c=d) is equivalent to broadcast((a,b) -> F(a, b; c=d), a, b). That is, it does not broadcast over the keyword arguments, but instead passes them inside the closure.

10 Likes

Any workaround to broadcast the keyword arguments? Should I lower these to a _func?

1 Like

Just call broadcast explicitly and you can use whatever arguments you want.

3 Likes

This is suppose to be a friendly end-user API… I ended up lowering the function and checking whether any of the arguments where AbstractVector to decide on whether to broadcast or not. Poor man type dispatch since there are too many combinations for a simple type dispatch.

I came across this thread after encountering a similar situation. The code below seems to offer a feasible solution. Note that there might be a small performance penalty for very simple functions, such as the example below, but it seems to be negligible in most cases.

f(a,b) = a + b
f(;a,b) = f.(a,b)

Output:

julia> f(;a=1,b=2)
3

julia> f(;a=1,b=[1,2])
2-element Array{Int64,1}:
 2
 3

A simple solution is to define a wrapper function:

wrap(a, b, c) = f(a, b; c=c)
wrap.(A, B, C) # broadcasts on three args.
1 Like

Is this documented somewhere? In the sense one can rely on this behavior and it won’t change except in 2.0.

I can’t find mention of keyword args in Single- and multi-dimensional Arrays · The Julia Language.

It should be documented; I’ve made a PR: document behavior of keywords in dot calls by stevengj · Pull Request #44033 · JuliaLang/julia · GitHub

2 Likes

Great, thanks.

d = 10
x = (;a= 1:3, b=2:4)

f(d;a,b) = d + a * b

one way to apply f to the elements of a and b is:

using DataFramesMeta

@rtransform DataFrame(x) :f = f(d; AsTable(:)... )

Ideally I’d like to write

f.(d; x... )

Will this be supported in 2.0 ?
Is there a better way now? without a function specific wrapper.
I don’t think broacast works due to the named tuple

Maybe DataPipes.jl does what you want?

And if you use StructArrays.jl you can seamlessly convert between named tuple of vectors and vector of names tuples

Thanks Peter. I couldn’t find that in StructArrays.jl but found it in SplitApplyCombine.jl. So this works

@pipe invert(x) .|> f(d; _... )

Do you know if f.(d; x... ) will be supported in a later version ?