Broadcast over splatted tuples

I can’t figure out the syntax for doing broadcasting and splatting at the same time
Example:

func(x1, x2) = x1+x2
v = collect(zip(rand(100), rand(100)));

I have function func which takes 2 arguments, and I have vector of tuples. I could splat one element like func(v[1]...). How can I broadcast over the splatted tuples? This doesn’t work: func.(v...). I guess it makes sense, because the splat is being applied to the vector when it should be applied to the elements of the vector, and we really want to broadcast the splatting before broadcasting func. I looked to see if there’s some splat keyword that implements the splatting, so I could do func.(splat.(v)), but it seems such keyword doesn’t exist.

Help?

3 Likes

Nice question! This is also something I struggle with. Best I could come up with is

julia> [func(t...) for t in v]
100-element Array{Float64,1}:
 0.7858096481491528
 1.6654849232758508
 1.8326554485741802
 ...
3 Likes

Of couse we can also write it using a map:

map(x -> func(x...), a);
2 Likes

You should also be able to do Base.splat(func).(v)

4 Likes

Oh interesting, so a splat function actually exists. Do you know how the splat symbols ... are implemented in terms of the splat function?

The splatting operator ... is a language feature, while the splat(fun) function is an adaptor exactly for the case that you mentioned. Implementation and docstring:

https://github.com/JuliaLang/julia/blob/76952a88ea650ae8c6b6b1d010ef695ed9c8244d/base/operators.jl#L1150

3 Likes

Haha indeed, the example is the same as mine :slight_smile: thank you for this.

As @FPGro pointed out, ... is not implemented in terms of Base.splat, but is actually lowered to a call to Core._apply_iterate. You could even write what you want like this:

julia> Core._apply_iterate.(iterate, func, v)
100-element Vector{Float64}:
[...]

(but it’s really an implementation detail, so probably don’t do that)

2 Likes