# Providing hints to broadcast?

**URL:** <https://discourse.julialang.org/t/providing-hints-to-broadcast/28137>\
**Category:** New to Julia\
**Created:** [August 28, 2019, 8:54pm UTC](https://discourse.julialang.org/t/providing-hints-to-broadcast/28137 "2019-08-28T20:54:17Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![wsphillips](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wsphillips/32/6777_2.png) [@wsphillips](https://discourse.julialang.org/u/wsphillips)\
**Post date:** [August 28, 2019, 8:54pm UTC](https://discourse.julialang.org/t/providing-hints-to-broadcast/28137/1 "2019-08-28T20:54:18Z")

</div>

I often run into this situation and have yet to find a solution other than writing a for-loop.  
Is there a way to vectorize the MWE below using features in Base?

Suppose I have a function accepting a 2d array and two integers that returns a transformed array:

```julia
function foo(a::Array{Float64,2}, b::Int, c::Int)
    #some transform
    return newa
end

```

I want to be able to generalize the usage of `foo()` with a broadcast:

```julia
a = ones(5,5)
b = [1,2,3]
c = [1,2,3]
result = zeros(5,5,3)
result .= foo.(a, b, c)

```

In this case I would intuit that `a` gets expanded on its 3rd dimension. However, broadcast can’t handle that. The closest one-liner solution I can come up with is:

```julia
result = foo.([a],b,c)

```

…but this returns an Array of Arrays which obviously isn’t great either.

I had thought the fairly recent addition of `eachslice()` might help but it doesn’t so much in this situation.

Any ideas? Is it possible to provide a clue to broadcast that indicates how the first Array should be expanded? Or is it “just write a for loop”???

---

<div class="post-metadata">

**Author:** ![shipengcheng1230](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shipengcheng1230/32/4089_2.png) [@shipengcheng1230](https://discourse.julialang.org/u/shipengcheng1230)\
**Post date:** [August 28, 2019, 8:57pm UTC](https://discourse.julialang.org/t/providing-hints-to-broadcast/28137/2 "2019-08-28T20:57:21Z")

</div>

One way, probably not so efficient, is to add a singleton dimension to hint the broadcast:  
[https://stackoverflow.com/questions/42312319/how-do-i-add-a-dimension-to-an-array-opposite-of-squeeze](https://stackoverflow.com/questions/42312319/how-do-i-add-a-dimension-to-an-array-opposite-of-squeeze)

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [August 28, 2019, 9:05pm UTC](https://discourse.julialang.org/t/providing-hints-to-broadcast/28137/3 "2019-08-28T21:05:30Z")

</div>

Lift `b` and `c` into that third dimension:

```julia
result .= foo.(a, reshape(b, 1, 1, :), reshape(c, 1, 1, :))

```

---

<div class="post-metadata">

**Author:** ![wsphillips](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wsphillips/32/6777_2.png) [@wsphillips](https://discourse.julialang.org/u/wsphillips)\
**Post date:** [August 28, 2019, 9:22pm UTC](https://discourse.julialang.org/t/providing-hints-to-broadcast/28137/4 "2019-08-28T21:22:00Z")

</div>

Both replies involve using `reshape` to “add” the missing dimension. However, this (surprisingly) also doesn’t work.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [August 28, 2019, 9:28pm UTC](https://discourse.julialang.org/t/providing-hints-to-broadcast/28137/5 "2019-08-28T21:28:03Z")

</div>

> [@wsphillips](#):
>
> foo(a::Array{Float64,2}, b::Int, c::Int)

Oh, I missed the signature of `foo(a::Array{Float64,2}, b::Int, c::Int)`. My answer assumes that `foo` is truly a scalar operation and operates element wise across all three arrays. You want to operate element wise across `b` and `c`, but treat `a` as an array, _and_ concatenate the answers into a third dimension. That’s simply not what broadcast does.

---

<div class="post-metadata">

**Author:** ![wsphillips](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wsphillips/32/6777_2.png) [@wsphillips](https://discourse.julialang.org/u/wsphillips)\
**Post date:** [August 28, 2019, 9:33pm UTC](https://discourse.julialang.org/t/providing-hints-to-broadcast/28137/6 "2019-08-28T21:33:35Z")

</div>

Yeah, I assumed it was pushing things into odd territory. But seeing as I often pleasantly find clever (often undocumented) tricks, worth an ask. I will likely just write an extra dispatch that envelops the original function in a for loop. Thanks!

---

<div class="post-metadata">

**Author:** ![feanor12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/feanor12/32/8212_2.png) [@feanor12](https://discourse.julialang.org/u/feanor12)\
**Post date:** [August 28, 2019, 9:42pm UTC](https://discourse.julialang.org/t/providing-hints-to-broadcast/28137/7 "2019-08-28T21:42:58Z")

</div>

Does Ref work?  
`foo.(Ref(a),b,c)`

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [August 28, 2019, 9:47pm UTC](https://discourse.julialang.org/t/providing-hints-to-broadcast/28137/8 "2019-08-28T21:47:25Z")

</div>

It’s the concatenating part that’s the challenge to express with broadcast alone.

Using Ref is the same as doing `[a]`, which was tried in the original post and returns an array of arrays. You can always concatenate them together afterwards, though.

---

<div class="post-metadata">

**Author:** ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)\
**Post date:** [August 28, 2019, 10:02pm UTC](https://discourse.julialang.org/t/providing-hints-to-broadcast/28137/9 "2019-08-28T22:02:05Z")

</div>

A nice way to combine slices is the package [JuliennedArrays](https://github.com/bramtayl/JuliennedArrays.jl):

```julia
julia> foo(a::Array{Float64,2}, b::Int, c::Int) = a .+ (b+c); # for example

julia> using JuliennedArrays

julia> collect(Align(foo.(Ref(a),b,c), 2,3))
3×5×5 Array{Float64,3}:
[:, :, 1] =
 3.0 3.0 3.0 3.0 3.0
 5.0 5.0 5.0 5.0 5.0
 7.0 7.0 7.0 7.0 7.0

[:, :, 2] =
 3.0 3.0 3.0 3.0 3.0

```

I think you can also write `reshape(reduce(hcat, foo.(Ref(a),b,c) ), (5,5,3))` but it’s possible I messed up the order of sizes here.
