# Style question: replacing multidimensional collect with broadcast

**URL:** <https://discourse.julialang.org/t/style-question-replacing-multidimensional-collect-with-broadcast/23464>\
**Category:** General Usage\
**Tags:** question\
**Created:** [April 24, 2019, 8:07am UTC](https://discourse.julialang.org/t/style-question-replacing-multidimensional-collect-with-broadcast/23464 "2019-04-24T08:07:08Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [April 24, 2019, 8:07am UTC](https://discourse.julialang.org/t/style-question-replacing-multidimensional-collect-with-broadcast/23464/1 "2019-04-24T08:07:08Z")

</div>

What’s the recommended way of writing something like

```julia
[f(i, j) for i in 1:I, j in 1:J]

```

using broadcasting? Eg

```julia
f.(1:I, (1:J)')
f.(1:I, permutedims(1:J))

```

?

This is purely a style question. Transpose feels icky (relies on `1'==1`), permutedims is long.

---

<div class="post-metadata">

**Author:** ![zgornel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zgornel/32/217487_2.png) [@zgornel](https://discourse.julialang.org/u/zgornel)\
**Post date:** [April 24, 2019, 7:49pm UTC](https://discourse.julialang.org/t/style-question-replacing-multidimensional-collect-with-broadcast/23464/2 "2019-04-24T19:49:13Z")

</div>

I personally like the icky version more 😉 (comprehension even better, despite the performance issue)

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [April 24, 2019, 8:31pm UTC](https://discourse.julialang.org/t/style-question-replacing-multidimensional-collect-with-broadcast/23464/3 "2019-04-24T20:31:48Z")

</div>

How about this `outer()` function? [Outer broadcasting? - #6 by rdeits](https://discourse.julialang.org/t/outer-broadcasting/22701/6)

Or we could turn that into a macro so that the result would fuse (I think) with any outer broadcasting operations.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [April 25, 2019, 5:43am UTC](https://discourse.julialang.org/t/style-question-replacing-multidimensional-collect-with-broadcast/23464/4 "2019-04-25T05:43:15Z")

</div>

I am not sure there is a performance issue; differences are minor and the order depends on the size.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [April 25, 2019, 5:44am UTC](https://discourse.julialang.org/t/style-question-replacing-multidimensional-collect-with-broadcast/23464/5 "2019-04-25T05:44:57Z")

</div>

Thanks for linking that topic, I see that this is an open question. Yes, somehow having a shorthand that combines well with broadcasting would be nice.

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [April 25, 2019, 6:21am UTC](https://discourse.julialang.org/t/style-question-replacing-multidimensional-collect-with-broadcast/23464/6 "2019-04-25T06:21:02Z")

</div>

How about a syntax `f.↑(1:I, 1:J)` so that you can do, e.g.,

```julia
julia> tuple.↑([1,2,3],[4,5])
3×2 Array{Tuple{Int64,Int64},2}:
 (1, 4) (1, 5)
 (2, 4) (2, 5)
 (3, 4) (3, 5)

```

Here is an implementation based on @rdeits’s `outer`:

```julia
@generated function outer_broadcasted(f, args::Tuple{Vararg{Any, N}}) where {N}
    expr = Expr(:call, Broadcast.broadcasted, :f) # instead of broadcast
    for i in 1:N
        if i == 1
            push!(expr.args, :(args[1]))
        else
            push!(expr.args, Expr(:call, :reshape, :(args[$i]), Expr(:tuple, [1 for _ in 1:i - 1]..., :(:))))
        end
    end
    expr
end

↑(f, args::Tuple) = Broadcast.materialize(f.↑(args))
Broadcast.broadcasted(::typeof(↑), f, args) = outer_broadcasted(f, args)

```

It’ll be fused with other dotted functions:

```julia
julia> Meta.@lower f.↑(x, y) .+ z
:($(Expr(:thunk, CodeInfo(
1 ─ %1 = (Core.tuple)(x, y)
│ %2 = (Base.broadcasted)(↑, f, %1)
│ %3 = (Base.broadcasted)(+, %2, z)
│ %4 = (Base.materialize)(%3)
└── return %4
))))

```

A downside is that `f.↑(x, y) .^ z` does not work as you’d expect.

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [April 25, 2019, 7:32am UTC](https://discourse.julialang.org/t/style-question-replacing-multidimensional-collect-with-broadcast/23464/7 "2019-04-25T07:32:31Z")

</div>

How about making `vec(x, d)` create a vector along dimension `d`? (Not type-stable in the general case, but `d` would typically be a literal.) Then one would write `f.(1:I, vec(1:J, 2))`, which is slightly shorter than `premutedims` and also generalizes better to higher dimension.

For an even shorter alternative, map some Unicode operator to `vec` so that one can write `f.(1:I, 1:J⇾2)` or similar.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [April 25, 2019, 7:44am UTC](https://discourse.julialang.org/t/style-question-replacing-multidimensional-collect-with-broadcast/23464/8 "2019-04-25T07:44:28Z")

</div>

And then make

```julia
vec(n::Int, dim::Int) = vec(Base.OneTo(n), dim)

```

I like this very much. Maybe I will experiment with this as a mini-package, also solving the [n x 1 array creation problem](https://discourse.julialang.org/t/literal-representation-of-array-t-2-when-the-array-is-nx1/8821).
