Broadcast multi-valued function over array

I have a multi-valued function, e.g., (x,y)->F(x,y)=(fx(x,y), fy(x,y)), where I would like to redefine its broadcast behavior, such that F.(xArray,yArray) returns (fx.(xArray,yArray), fy.(xArray, yArray)), instead of the standard Array((fx(x,y),fy(x,y)) for x,y in (xArray,yArray)). In other words I want tuple of arrays rather than array of tuples as return types. Is there a proper way to redefine the function F 's broadcast behavior over all broadcastables, including arrays, tuples, etc? I don’t want additional allocations to be involved, e.g., getindex.(...)

You could use the StructArrays.jl package, which allows you to construct an array that acts like an array of tuples but is actually a tuple of arrays (which can then be extracted without making a copy). For example:

julia> using StructArrays

julia> f(x) = (x+1, x+2)   # example function returning a tuple
f (generic function with 1 method)

julia> y = StructArray{Tuple{Int, Int}}(undef, 5);

julia> y .= f.(1:5)
5-element StructArray(::Vector{Int64}, ::Vector{Int64}) with eltype Tuple{Int64, Int64}:
 (2, 3)
 (3, 4)
 (4, 5)
 (5, 6)
 (6, 7)

julia> a, b = StructArrays.components(y)  # tuple of arrays
([2, 3, 4, 5, 6], [3, 4, 5, 6, 7])
5 Likes