# Broadcast over a multiple output function and receive a Tuple of Arrays

**URL:** <https://discourse.julialang.org/t/broadcast-over-a-multiple-output-function-and-receive-a-tuple-of-arrays/91111>\
**Category:** General Usage\
**Tags:** question, splitapplycombine\
**Created:** [December 1, 2022, 7:00pm UTC](https://discourse.julialang.org/t/broadcast-over-a-multiple-output-function-and-receive-a-tuple-of-arrays/91111 "2022-12-01T19:00:59Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![bensetterholm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bensetterholm/32/12792_2.png) [@bensetterholm](https://discourse.julialang.org/u/bensetterholm)\
**Post date:** [December 1, 2022, 7:00pm UTC](https://discourse.julialang.org/t/broadcast-over-a-multiple-output-function-and-receive-a-tuple-of-arrays/91111/1 "2022-12-01T19:00:59Z")

</div>

Is there a convenient way to broadcast over a function that produces multiple outputs and receive a tuple of arrays instead of an array of tuples?

For example, with the `sincos` function, I get the following output upon broadcast:

```julia
julia> sincos.(2:4)
3-element Vector{Tuple{Float64, Float64}}:
 (0.9092974268256817, -0.4161468365471424)
 (0.1411200080598672, -0.9899924966004454)
 (-0.7568024953079282, -0.6536436208636119)

```

but what I want is:

```julia
([0.9092974268256817, 0.1411200080598672, -0.7568024953079282], [-0.4161468365471424, -0.9899924966004454, -0.6536436208636119])

```

The ugly solution I though of would be to do

```julia
let a = sincos.(2:4)
    Tuple([[b[i] for b in a] for i in eachindex(a[1])])
end

```

but this has way too much allocation overhead.

(I know for this particular example I could do `(sin.(2:4), cos.(2:4))`, but I am asking for functions in general, assuming there are no separate `sin` and `cos` methods. Ultimately, I would like to do something along the lines of `s, c = sincos.(2:4)` where `s == sin.(2:4)` and `c == cos.(2:4)`)

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [December 1, 2022, 7:32pm UTC](https://discourse.julialang.org/t/broadcast-over-a-multiple-output-function-and-receive-a-tuple-of-arrays/91111/3 "2022-12-01T19:32:31Z")

</div>

Here’s some code I use for re-packing data:

```julia
function repack(x::AbstractArray{T}) where T<:Tuple
	# turn Array{Tuple{T1,T2...}} to Tuple{Array{T1},Array{T2},...}
	fT = ntuple(i->fieldtype(T,i),fieldcount(T)) # fieldtypes(T) would be the obvious choice but was type-unstable when I tried
	arrs = similar.(Ref(x),fT)
	for i in eachindex(x,arrs...)
		@inbounds setindex!.(arrs,x[i],Ref(i))
	end
	return arrs
end
function repack(x::AbstractArray{NamedTuple{N,T}}) where {N,T<:Tuple}
	# turn Array{NamedTuple{N,Tuple{T1,T2...}}} to NamedTuple{N,Tuple{Array{T1},Array{T2},...}}
	fT = ntuple(i->fieldtype(T,i),fieldcount(T)) # fieldtypes(T) would be the obvious choice but was type-unstable when I tried
	arrs = similar.(Ref(x),fT)
	for i in eachindex(x,arrs...)
		@inbounds setindex!.(arrs,Tuple(x[i]),Ref(i))
	end
	return NamedTuple{N}(arrs)
end

```

But this ultimately still requires extra allocations over what could be a variant of `map` that returns tuples-of-arrays rather than arrays-of-tuples. You can certainly achieve this with preallocation and a loop, but that’s only nice if you know the number and types of outputs of your function (which can be annoying to determine programmatically – `map` and `broadcast` are so nice because they don’t require you to do this manually). Maybe someone will eventually implement this `map` variant, but it doesn’t exist yet.

You can also look into `StructArrays.jl`, which may have some utilities for this sort of situation.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [December 1, 2022, 7:56pm UTC](https://discourse.julialang.org/t/broadcast-over-a-multiple-output-function-and-receive-a-tuple-of-arrays/91111/4 "2022-12-01T19:56:00Z")

</div>

One more option:

```julia
using SplitApplyCombine
invert(sincos.(2:4)) 

```

---

<div class="post-metadata">

**Author:** ![bensetterholm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bensetterholm/32/12792_2.png) [@bensetterholm](https://discourse.julialang.org/u/bensetterholm)\
**Post date:** [December 1, 2022, 8:06pm UTC](https://discourse.julialang.org/t/broadcast-over-a-multiple-output-function-and-receive-a-tuple-of-arrays/91111/5 "2022-12-01T20:06:03Z")

</div>

Wow, this package is exactly what I was looking for. Thanks!
