# What is the cleanest way to broadcast a multi-variate function over all input vectors

**URL:** <https://discourse.julialang.org/t/what-is-the-cleanest-way-to-broadcast-a-multi-variate-function-over-all-input-vectors/84599>\
**Category:** New to Julia\
**Tags:** broadcast\
**Created:** [July 21, 2022, 5:52pm UTC](https://discourse.julialang.org/t/what-is-the-cleanest-way-to-broadcast-a-multi-variate-function-over-all-input-vectors/84599 "2022-07-21T17:52:32Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![jinml](https://avatars.discourse-cdn.com/v4/letter/j/91b2a8/32.png) [@jinml](https://discourse.julialang.org/u/jinml)\
**Post date:** [July 21, 2022, 5:52pm UTC](https://discourse.julialang.org/t/what-is-the-cleanest-way-to-broadcast-a-multi-variate-function-over-all-input-vectors/84599/1 "2022-07-21T17:52:32Z")

</div>

For example, I have a function `f(x,y,z)` and three vectors `x, y, z`. I’d like to compute all combinations and return a 3D array of values. What I can do is this: `f.(x,y',reshape(z,1,1,:))`. Is there a less cumbersome way, e.g., a macro, to do the same? Also the `'` will conjugate if `y` were complex, which is not very clean.

---

<div class="post-metadata">

**Author:** ![VaclavMacha](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vaclavmacha/32/20825_2.png) [@VaclavMacha](https://discourse.julialang.org/u/VaclavMacha)\
**Post date:** [July 21, 2022, 7:14pm UTC](https://discourse.julialang.org/t/what-is-the-cleanest-way-to-broadcast-a-multi-variate-function-over-all-input-vectors/84599/2 "2022-07-21T19:14:07Z")

</div>

It’s not exactly what you asked for, but I think it’s more readable

```julia
using Base.Iterators

f(x, y, z) = x + y + z
f(x) = f(x...)

x, y, z = rand(4), rand(3), rand(2)
f.(product(x, y, z))

```

---

<div class="post-metadata">

**Author:** ![jinml](https://avatars.discourse-cdn.com/v4/letter/j/91b2a8/32.png) [@jinml](https://discourse.julialang.org/u/jinml)\
**Post date:** [July 21, 2022, 9:27pm UTC](https://discourse.julialang.org/t/what-is-the-cleanest-way-to-broadcast-a-multi-variate-function-over-all-input-vectors/84599/3 "2022-07-21T21:27:01Z")

</div>

I found the following solution through `Tullio`:

```julia
using Tullio
@tullio v[i,j,k]:=f(x[i],y[j],z[k])

```

Looks quite intuitive

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [July 21, 2022, 10:49pm UTC](https://discourse.julialang.org/t/what-is-the-cleanest-way-to-broadcast-a-multi-variate-function-over-all-input-vectors/84599/4 "2022-07-21T22:49:56Z")

</div>

Is the broadcasting dot needed here? I would not expect so.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [July 22, 2022, 10:04am UTC](https://discourse.julialang.org/t/what-is-the-cleanest-way-to-broadcast-a-multi-variate-function-over-all-input-vectors/84599/5 "2022-07-22T10:04:32Z")

</div>

When you’re down to one multidimensional iterable, comprehension is neater than broadcasting and doesn’t require you to define the one-argument method to splat an input tuple: `[f(i...) for i in product(x, y, z)]`.

Broadcasting really is just awkward for this case because the inputs’ shapes determine the output’s shape, so the straightforward usage is indeed reshaping the input vectors to extend along different axes. It’s fine to use other ways when they are neater; they’re all looping a method call over the same elements anyway.

---

<div class="post-metadata">

**Author:** ![jondea](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jondea/32/39086_2.png) [@jondea](https://discourse.julialang.org/u/jondea)\
**Post date:** [July 22, 2022, 10:05am UTC](https://discourse.julialang.org/t/what-is-the-cleanest-way-to-broadcast-a-multi-variate-function-over-all-input-vectors/84599/6 "2022-07-22T10:05:05Z")

</div>

One clean way to do this is with generator expressions

```julia
[f(x,y,z) for x in 1:3, y in 1:5, z in 1:7]

```

it has the added benefit of being lazy, so operations like sum don’t need to allocate the whole 3D array

```julia
sum(f(x,y,z) for x in 1:3, y in 1:5, z in 1:7)

```

---

<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:** [July 22, 2022, 10:17am UTC](https://discourse.julialang.org/t/what-is-the-cleanest-way-to-broadcast-a-multi-variate-function-over-all-input-vectors/84599/7 "2022-07-22T10:17:25Z")

</div>

> [@jondea](#):
>
> generator expressions

What you wrote is a comprehension. The generator expressions have round brackets, right?

---

<div class="post-metadata">

**Author:** ![jondea](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jondea/32/39086_2.png) [@jondea](https://discourse.julialang.org/u/jondea)\
**Post date:** [July 22, 2022, 10:26am UTC](https://discourse.julialang.org/t/what-is-the-cleanest-way-to-broadcast-a-multi-variate-function-over-all-input-vectors/84599/8 "2022-07-22T10:26:25Z")

</div>

Indeed, a stand alone generator expression has round brackets. I did a comprehension because OP wanted an array. It may not be the case in the internals, but I think of a comprehension as a collected generator.
