# How to control the output of broadcast?

**URL:** <https://discourse.julialang.org/t/how-to-control-the-output-of-broadcast/32287>\
**Category:** New to Julia\
**Created:** [December 15, 2019, 3:23am UTC](https://discourse.julialang.org/t/how-to-control-the-output-of-broadcast/32287 "2019-12-15T03:23:04Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![tomtom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomtom/32/5106_2.png) [@tomtom](https://discourse.julialang.org/u/tomtom)\
**Post date:** [December 15, 2019, 3:23am UTC](https://discourse.julialang.org/t/how-to-control-the-output-of-broadcast/32287/1 "2019-12-15T03:23:04Z")

</div>

calling `fun.()` below returns an `Array` of `NamedTuple`s:

```julia
julia> function fun(x)::NamedTuple
           (a = x + 1, b = x - 1)
       end
fun (generic function with 1 method)

julia> fun.([1, 2, 3])
3-element Array{NamedTuple{(:a, :b),Tuple{Int64,Int64}},1}:
 (a = 2, b = 0)
 (a = 3, b = 1)
 (a = 4, b = 2)

```

however, I **want** the output to be:

```julia
(a = [2, 3, 4], b = [0, 1, 2])

```

i.e., a `NamedTuple` of `Array`s

of course I could manipulate the returns from `fun.`, but is there a **direct** way to control the output of “dot” functions?

thanks.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [December 15, 2019, 3:54am UTC](https://discourse.julialang.org/t/how-to-control-the-output-of-broadcast/32287/2 "2019-12-15T03:54:20Z")

</div>

the dot is just apply the function to each element of the array and that’s it.

You get what you should in this case.

---

<div class="post-metadata">

**Author:** ![recri](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/recri/32/5280_2.png) [@recri](https://discourse.julialang.org/u/recri)\
**Post date:** [December 15, 2019, 8:49am UTC](https://discourse.julialang.org/t/how-to-control-the-output-of-broadcast/32287/3 "2019-12-15T08:49:58Z")

</div>

You put the broadcast where it needs to be.

```julia
julia> fun(x)::NamedTuple = (a = x .+ 1, b = x .- 1)
fun (generic function with 1 method)

julia> fun([1,2,3])
(a = [2, 3, 4], b = [0, 1, 2])

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [December 15, 2019, 9:19am UTC](https://discourse.julialang.org/t/how-to-control-the-output-of-broadcast/32287/4 "2019-12-15T09:19:44Z")

</div>

> [@tomtom](#):
>
> course I could manipulate the returns from `fun.` , but is there a **direct** way to control the output of “dot” functions?

Dotted functions are special syntax, they’re not calling different versions of the original function. Since the broadcasting behaviour depends on the input types of the arguments, changing it in a generic way would probably be type piracy and have a bunch of unintended side effects in the case of your `Array` example.

For more info about broadcasting and how it works, see [here](https://docs.julialang.org/en/v1/base/arrays/#Broadcast-and-vectorization-1).

---

<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:** [December 16, 2019, 1:51am UTC](https://discourse.julialang.org/t/how-to-control-the-output-of-broadcast/32287/5 "2019-12-16T01:51:24Z")

</div>

You can kind of do it by combining StructArrays and LazyArrays:

```julia
julia> using StructArrays

julia> using LazyArrays: @~

julia> x = 1:2
1:2

julia> f(x) = (a=x+1, b=x-1)
f (generic function with 1 method)

julia> y = StructVector(@~ f.(x))
2-element StructArray(::Array{Int64,1}, ::Array{Int64,1}) with eltype NamedTuple{(:a, :b),Tuple{Int64,Int64}}:
 (a = 2, b = 0)
 (a = 3, b = 1)

julia> y.a
2-element Array{Int64,1}:
 2
 3

julia> y.b
2-element Array{Int64,1}:
 0
 1

julia> fieldarrays(y)
(a = [2, 3], b = [0, 1])

```

---

<div class="post-metadata">

**Author:** ![tomtom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomtom/32/5106_2.png) [@tomtom](https://discourse.julialang.org/u/tomtom)\
**Post date:** [February 27, 2020, 3:15pm UTC](https://discourse.julialang.org/t/how-to-control-the-output-of-broadcast/32287/6 "2020-02-27T15:15:17Z")

</div>

> [@tomtom](#):
>
> however, I **want** the output to be:
> 
> ```julia
> (a = [2, 3, 4], b = [0, 1, 2])
> 
> ```
> 
> i.e., a `NamedTuple` of `Array` s

today I finally “find out” a solution! 😀 let’s review the original situation:

```julia
f(x) = (a = g(x), b = h(x))
g(x) = x + 1
h(x) = x - 1

f.([1, 2, 3])

julia> f.([1, 2, 3])
3-element Array{NamedTuple{(:a, :b),Tuple{Int64,Int64}},1}:
 (a = 2, b = 0)
 (a = 3, b = 1)
 (a = 4, b = 2)

```

the trick is to

1. wrapping `Base.broadcasted`
2. override `Base.materialize` (and `Base.materialize!` if needed):

```julia
struct MyBC{Tf, S}
    content::S
    MyBC{Tf}(x) where {Tf} = new{Tf, typeof(x)}(x)
end

@inline Base.broadcasted(::typeof(f), x) = MyBC{typeof(f)}(x)
@inline Base.materialize(mybc::MyBC{typeof(f)}) = 
        (a = Base.materialize(Base.broadcasted(g, mybc.content)), 
         b = Base.materialize(Base.broadcasted(h, mybc.content)) )

julia> f.([1, 2, 3])
(a = [2, 3, 4], b = [0, 1, 2])

```

hope it helps 😃

---

<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:** [February 27, 2020, 9:02pm UTC](https://discourse.julialang.org/t/how-to-control-the-output-of-broadcast/32287/7 "2020-02-27T21:02:56Z")

</div>

This implementation is not composable with the rest of broadcasting mechanism. For example, this does not work:

```julia
sumab(x) = x.a + x.b
sumab.(f.([1, 2, 3]))

```

I think you need to use a custom broadcasting style to make it better.

---

<div class="post-metadata">

**Author:** ![tomtom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomtom/32/5106_2.png) [@tomtom](https://discourse.julialang.org/u/tomtom)\
**Post date:** [February 28, 2020, 1:23am UTC](https://discourse.julialang.org/t/how-to-control-the-output-of-broadcast/32287/8 "2020-02-28T01:23:58Z")

</div>

> [@tkf](#):
>
> This implementation is not composable with the rest of broadcasting mechanism

Yes and No. Remember that, as far as I know, broadcasting is original aimed for **scalar functions**. But now `f()` returns **a pair of values** (i.e. not a scalar), so naturally it can **not** be chained with other broadcasting **unless it’s the last** one:

```julia
julia> f.([1, 2, 3] .* 2 .+ 1)
(a = [4, 6, 8], b = [2, 4, 6])

```

which is fine.

or, if it’s not the last function, we could e.g.:

```julia
temp = f.([1, 2, 3])
julia> (temp[1] .* 2 .+ 1, temp[2] .* 3 .- 2)
([5, 7, 9], [-2, 1, 4])

```

that said, as `f()` is not a scalar function, we should not expect it could directly be broadcasted (in the middle of the chain) with others.

> [@tkf](#):
>
> need to use a custom broadcasting style

as I understand, a custom broadcasting style is used for a custom typed **argument** , e.g. a new type of vector. But now the thing needed to be specially handled is the **function** to be broadcasted, so I think it’s **irrelevant to broadcasting style**.  
Actually, this implementation handles different types of argument smoothly. For example, we can broadcast on a tuple rather than a vector:

```julia
julia> f.((10, 20) )
(a = (11, 21), b = (9, 19))

```
