# Custom broadcasting

**URL:** <https://discourse.julialang.org/t/custom-broadcasting/39945>\
**Category:** General Usage\
**Created:** [May 22, 2020, 8:40am UTC](https://discourse.julialang.org/t/custom-broadcasting/39945 "2020-05-22T08:40:26Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![tlienart](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tlienart/32/7640_2.png) [@tlienart](https://discourse.julialang.org/u/tlienart)\
**Post date:** [May 22, 2020, 8:40am UTC](https://discourse.julialang.org/t/custom-broadcasting/39945/1 "2020-05-22T08:40:26Z")

</div>

After spending quite a bit of time in the [Customizing broadcasting](https://docs.julialang.org/en/v1/manual/interfaces/#man-interfaces-broadcasting-1) section of the doc, reading a few questions here and trawling through the source code of StaticArrays.jl I’m throwing the sponge. (Once I’ve figured this out, I’ll try to help make this broadcasting section of the docs more accessible for the lay person like me…).

My specs are pretty simple:

```julia
struct MyType{R} <: AbstractVector{R}
  data::Matrix{R}
  metadata
end

```

I’d like to be able to do what’s required so that a user can do `f.(x)` where `x` is an instance of `MyType`. This is pretty much identical to the `ArrayAndChar` example from the docs with one difference: `data` is a Matrix, elements of MyType are the rows. Something like

```julia
Base.length(m::MyType) = size(m.data, 1)
Base.getindex(m::MyType, i::Integer) = m.data[i,:]
Base.getindex(m::MyType, I::AbstractVector{<:Integer}) = MyType(m.data[I, :], m.metadata)

```

What I’d like to do is that `f.(x)` applies `f` to rows of `x.data`. I don’t need operations etc, just this broadcasting rule. As a toy example, I’d like to be able to do `maximum.(x)` and get a vector of maxes i.e. similar as the `[maximum(x[i]) for i in 1:length(x)]`. (In practice I’d like `f` to make use of the metadata but that doesn’t seem to be the hard bit)

After thoroughly confusing myself between the custom `similar` and `copyto!`, I admit I don’t understand what’s going on, help would be very welcome, thanks!

---

<div class="post-metadata">

**Author:** ![ettersi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ettersi/32/6829_2.png) [@ettersi](https://discourse.julialang.org/u/ettersi)\
**Post date:** [May 22, 2020, 8:55am UTC](https://discourse.julialang.org/t/custom-broadcasting/39945/2 "2020-05-22T08:55:24Z")

</div>

Your type definition does not agree with your specification. Either you want

```julia
struct MyType{RowType} <: AbstractVector{RowType}
  data::Vector{RowType}
  metadata
end

```

or you want

```julia
struct MyType{ElType} <: AbstractVector{Vector{ElType}}
  data::Matrix{ElType}
  metadata
end

```

In the second case, you might further want to replace `Vector{ElType}` with a view for efficiency, but that is another layer of complexity which we can get into later.

---

<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:** [May 22, 2020, 9:25am UTC](https://discourse.julialang.org/t/custom-broadcasting/39945/3 "2020-05-22T09:25:47Z")

</div>

With this definition:

> [@ettersi](#):
>
> ```julia
> struct MyType{ElType} <: AbstractVector{Vector{ElType}}
> data::Matrix{ElType}
> metadata
> end
> 
> ```

and a method for `size`, simple broadcasting should work without any customising:

```julia
Base.size(x::MyType) = (size(x.data, 1),)
Base.getindex(x::MyType, i::Integer) = x.data[i,:]
m42 = MyType(rand(Int8,4,2), nothing) 
maximum.(m42) # works

```

How is `metadata` going to be used?

---

<div class="post-metadata">

**Author:** ![tlienart](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tlienart/32/7640_2.png) [@tlienart](https://discourse.julialang.org/u/tlienart)\
**Post date:** [May 22, 2020, 9:41am UTC](https://discourse.julialang.org/t/custom-broadcasting/39945/4 "2020-05-22T09:41:10Z")

</div>

Thanks a lot for your answers, I understand the original mistake. There may be a further spec I should have mentioned.

What I’d like is that the `data` is either a `Vector{R}` or a `Matrix{R}`. In the first case the type should be subtype of `AbstractVector{R}`, in the second `AbstractVector{Vector{R}}` as per @ettersi’s comment. I understand from both your comments that if this subtyping is done properly I wouldn’t have to bother with `similar` and `copyto!`.

In non-valid code I guess I’d like to have something like

```julia
struct MyType{R,E<:Union{R,Vector{R}}} <: AbstractVector{E}
  data::Array{R, E == R ? 1 : 2}
  metadata
end

```

**Edit** : the following seems to do what I want

```julia
struct MyType3{R,D,E<:Union{R,Vector{R}}} <: AbstractVector{E}
  data::Array{R,D}
  MyType3(m::Matrix{R}) where R = new{R,2,Vector{R}}(m)
  MyType3(v::Vector{R}) where R = new{R,1,R}(v)
end

mt2 = MyType3(rand(5, 2));
mt1 = MyType3(rand(5));

Base.size(m::MyType3) = (size(m.data,1),)
Base.length(m::MyType3) = size(m.data,1)

Base.getindex(m::MyType3{R,1}, i::Int) where R = m.data[i]
Base.getindex(m::MyType3{R,2}, i::Int) where R = m.data[i,:]

mt2[1]

mt1[1]

foo(x) = sum(x.^2)

foo.(mt1)
foo.(mt2)

```

---

<div class="post-metadata">

**Author:** ![henry2004y](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henry2004y/32/9284_2.png) [@henry2004y](https://discourse.julialang.org/u/henry2004y)\
**Post date:** [January 5, 2021, 9:47am UTC](https://discourse.julialang.org/t/custom-broadcasting/39945/5 "2021-01-05T09:47:40Z")

</div>

I am completely new to this topic and happened to find the discussions here.

I have a question regarding subtypes here: with the `<:` syntax, are we saying that our custom type is a subtype of `AbstractVector{R}` or `AbstractVector{Vector{ElType}}`? And why do we need to explicitly write this, otherwise the custom broadcasting won’t work?

In a more general context, do we need to specify the abstract supertypes for our custom types?

---

<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:** [January 5, 2021, 1:27pm UTC](https://discourse.julialang.org/t/custom-broadcasting/39945/6 "2021-01-05T13:27:43Z")

</div>

No, you don’t need to subtype anything in order to participate in or customize broadcasting. But if you do, you must behave as we’d expect that abstract type to behave.

Subtyping `<: AbstractArray` gives you lots of behaviors “for free,” but you must obey the rules for an AbstractArray in order for those behaviors to work. Whether you use `<: AbstractVector{R}` or `AbstractVector{Vector{ElType}}` or something different entirely all comes down to how you want your type to behave.
