Destructuring and broadcast

question

#1

If I want to broadcast a function that returns a tuple, is there a simple way to “broadcast” the left hand side destructuring?

a = 1:10
b = 11:20

transform(a, b) = a+b, a*b, a-b # MWE, the real one is more compicated

## want something like (syntax of course does not work)
@. x, y, z = transform(a, b)

## of course I can do
w = transform.(a,b)
x = first.(w)
y = (v->v[2]).(w)
z = last.(w)

Questiosn about `where` for function definitions (while unpacking arrays of tuples)
#2

I don’t know about simple, but I had the same problem and came up with this oneliner for creating NTuples:

x,y,z = collect(zip(transform.(a,b)...))

If you absolutely need Vectors then add another collect:

x,y,z = collect.(collect(zip(transform.(a,b)...)))

But I’m still a newbie, so I’m sure there’s a better way. I’m curious to see what the pros come up with.


#3

Hi,

I have a similar issue: I don’t know how to obtain a tuple of arrays instead of an array of tuples.

The answer by @NickNack works for simple cases, but loses track of resulting shape when the broadcast results in more than one dimension.

# compute on a 2d grid
x1 = reshape(1:5,  (5,1)) 
x2 = reshape(6:11, (1,6))
typeof(collect(zip(transform.(x1,x2)...))) # Array{NTuple{30,Int64},1}

This result is different from the solution by @Tamas_Papp, which correctly preserves the shape of the resulting arrays.

Coming from python/numpy, I am used to this situation resulting in tuple of arrays instead of array of tuples. Anybody knows a way to obtain similar behavior in julia?

The equivalent numpy code:

import numpy as np

def transform(a, b):
    return a+b, a*b, a-b

x1 = np.arange(1, 6).reshape((5,1))
x2 = np.arange(6, 12).reshape((1,6))
u, v, w = transform(x1, x2)

Potentially related:
https://github.com/JuliaLang/julia/issues/13942

None of the proposed solutions seem to work here, upon a very superficial quick try.