# Custom broadcasting for static, immutable type

**URL:** <https://discourse.julialang.org/t/custom-broadcasting-for-static-immutable-type/69426>\
**Category:** General Usage\
**Tags:** question, broadcast, struct, staticarrays\
**Created:** [October 8, 2021, 9:17am UTC](https://discourse.julialang.org/t/custom-broadcasting-for-static-immutable-type/69426 "2021-10-08T09:17:17Z")\
**Posts on this page:** 2\
**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:** [October 8, 2021, 9:17am UTC](https://discourse.julialang.org/t/custom-broadcasting-for-static-immutable-type/69426/1 "2021-10-08T09:17:17Z")

</div>

Consider the following type with two fields,

```julia
using StaticArrays

struct Foo{T,N}
    x::T
    y::SVector{N,T}
end

```

The objective is to

1. make broadcasting work for matching dimension `N` and scalars,
2. error for everything else

Eg the following should work:

```julia
x = Foo(1, SVector(2, 3))
x .+ 3
(x .+ x) ./ 2

```

but eg `x .+ 1:3` should not.

Based on the manual, I implemented this as

```julia
Broadcast.broadcastable(x::Foo) = x

struct FooStyle{N} <: Broadcast.BroadcastStyle end

Broadcast.BroadcastStyle(::Type{Foo{T,N}}) where {T,N} = FooStyle{N}()

Broadcast.BroadcastStyle(::FooStyle{N}, ::Broadcast.DefaultArrayStyle{0}) where N = FooStyle{N}()

function Broadcast.materialize(B::Broadcast.Broadcasted{FooStyle{N}}) where N
    flat = Broadcast.flatten(B)
    args = flat.args
    f = flat.f
    xs = map(a -> a isa Foo ? a.x : Ref(a), args)
    ys = map(a -> a isa Foo ? a.y : Ref(a), args)
    Foo(f.(xs...), f.(ys...))
end

```

It seems to work — I am kind of surprised how easy it was. Is this all I need, or did I miss anything?

---

<div class="post-metadata">

**Author:** ![ederag](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ederag/32/4106_2.png) [@ederag](https://discourse.julialang.org/u/ederag)\
**Post date:** [August 2, 2022, 2:35pm UTC](https://discourse.julialang.org/t/custom-broadcasting-for-static-immutable-type/69426/2 "2022-08-02T14:35:45Z")

</div>

Thanks a lot ! This allowed me to set up broadcast with a wrapper around an SVector as well.

`materialize` disappeared from the [documentation](https://docs.julialang.org/en/v1/manual/interfaces/#man-interfaces-broadcasting),  
which seems focused on mutable types.  
But after looking into `broadcast.jl`, it looks like the `Ref(a)` are not needed (`a` is enough):

```julia
function Broadcast.materialize(B::Broadcast.Broadcasted{FooStyle{N}}) where N
	    flat = Broadcast.flatten(B)
	    args = flat.args
	    f = flat.f
	    xs = map(a -> a isa Foo ? a.x : a, args)
	    ys = map(a -> a isa Foo ? a.y : a, args)
	    Foo(f.(xs...), f.(ys...))
	end

```

Otherwise some operations like `convert.(Int32, x)` fails.

Or is there a catch ?
