# Broadcast for custom type

**URL:** https://discourse.julialang.org/t/broadcast-for-custom-type/3497
**Category:** General Usage
**Tags:** question, broadcast
**Created:** [May 3, 2017, 11:31am UTC](https://discourse.julialang.org/t/broadcast-for-custom-type/3497 "2017-05-03T11:31:33Z")
**Posts on this page:** 1
**Showing post:** 3

<div class="post-metadata">

### Author: ![fengyang.wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fengyang.wang/32/104_2.png) [@fengyang.wang](https://discourse.julialang.org/u/fengyang.wang)
#### Post date: [May 4, 2017, 7:18am UTC](https://discourse.julialang.org/t/broadcast-for-custom-type/3497/3 "2017-05-04T07:18:08Z")

</div>

This does need to be documented better. In the meantime, consider the following pointers that may help:

- @davidanthoff’s implementation of `broadcast` for DataValues.jl: [https://github.com/davidanthoff/DataValues.jl/pull/9/files](https://github.com/davidanthoff/DataValues.jl/pull/9/files)

This is a lightly edited version of a “minimal working example” I posted on Gitter, during a discussion with @ChrisRackauckas :

Depending on your use case you can choose to use as much or as little of the generic broadcast code as is necessary. Generally, you do **not** specialize `broadcast`, but rather `broadcast_c`.

I have a quick demo of what `broadcast_c` means:

```julia
julia> struct Poison end

julia> Base.Broadcast._containertype(::Type{<:Poison}) = Poison

julia> Base.Broadcast.promote_containertype(::Type{Poison}, _) = Poison

julia> Base.Broadcast.promote_containertype(_, ::Type{Poison}) = Poison

julia> Base.Broadcast.promote_containertype(::Type{Poison}, ::Type{Array}) = Poison

julia> Base.Broadcast.promote_containertype(::Type{Array}, ::Type{Poison}) = Poison

julia> Base.Broadcast.broadcast_c(f, ::Type{Poison}, _...) = "hijacked broadcasting"

julia> Poison() .+ [1, 2, 3]
"hijacked broadcasting"

```

- roughly, the way `broadcast` works is: it looks at the argument types it gets and tries to determine which `broadcast_c` method handles broadcasting of those types.
- first it calls `_containertype` on the types of all arguments
- then it calls `promote_containertype` on all of the return values of `_containertype`

So the part to ensure that `Broadcast` will dispatch to your desired `broadcast_c` method is:

```julia
struct Poison end
Base.Broadcast._containertype(::Type{<:Poison}) = Poison
Base.Broadcast.promote_containertype(::Type{Poison}, _) = Poison
Base.Broadcast.promote_containertype(_, ::Type{Poison}) = Poison

```

and the part actually defining the broadcast behavior is:

```julia
Base.Broadcast.broadcast_c(f, ::Type{Poison}, _...) = "hijacked broadcasting"

```

Why do we need to treat arrays separately? In this case, because of ambiguities. The broadcast code in `Base` itself has the equivalent of

```julia
promote_containertype(::Type{Array}, _) = Array
promote_containertype(_, ::Type{Array}) = Array

```

so there will be ambiguities unless you treat arrays with their own extra methods.

Note `broadcast` dispatches to `broadcast_c` and `broadcast!(f, ::AbstractArray, ...)` dispatches to `broadcast_c!` in roughly the same way. Note that `broadcast!` by default is only defined for the LHS an `AbstractArray`. If you have your own type on the LHS you will need to specialize `broadcast!` directly instead of `broadcast_c!` (or perhaps in addition to, if you’d like to call broadcast\_c!).

So in summary:

- Do not add methods to `broadcast`.
- Instead, add methods to `broadcast_c`, which has the same signature of `broadcast` except an additional argument is added after the function argument, which will be a `::Type{...}` of your choosing.
- Then, add methods to `_containertype` and `promote_containertype` so that the generic `broadcast` can pick the correct method.
- The same applies for `broadcast!` and `broadcast_c!`, except that when the LHS is not an `AbstractArray`, additional methods may be required.

---

_[View the full topic](https://discourse.julialang.org/t/broadcast-for-custom-type/3497)._
