# Defining broadcast for custom types - the example in the docs fails

**URL:** <https://discourse.julialang.org/t/defining-broadcast-for-custom-types-the-example-in-the-docs-fails/32291>\
**Category:** General Usage\
**Tags:** broadcast\
**Created:** [December 15, 2019, 6:16am UTC](https://discourse.julialang.org/t/defining-broadcast-for-custom-types-the-example-in-the-docs-fails/32291 "2019-12-15T06:16:36Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![fjarri](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fjarri/32/630_2.png) [@fjarri](https://discourse.julialang.org/u/fjarri)\
**Post date:** [December 15, 2019, 6:16am UTC](https://discourse.julialang.org/t/defining-broadcast-for-custom-types-the-example-in-the-docs-fails/32291/1 "2019-12-15T06:16:36Z")

</div>

I’m using the [example from the docs](https://docs.julialang.org/en/latest/manual/interfaces/#Selecting-an-appropriate-output-array-1):

```julia
struct ArrayAndChar{T,N} <: AbstractArray{T,N}
    data::Array{T,N}
    char::Char
end

Base.size(A::ArrayAndChar) = size(A.data)
Base.getindex(A::ArrayAndChar{T,N}, inds::Vararg{Int,N}) where {T,N} = A.data[inds...]
Base.setindex!(A::ArrayAndChar{T,N}, val, inds::Vararg{Int,N}) where {T,N} = A.data[inds...] = val
Base.show(io::IO, A::ArrayAndChar) = print(io, typeof(A), " ", A.data, " with char '", A.char, "'")

Base.BroadcastStyle(::Type{<:ArrayAndChar}) = Broadcast.ArrayStyle{ArrayAndChar}()

function Base.similar(bc::Broadcast.Broadcasted{Broadcast.ArrayStyle{ArrayAndChar}}, ::Type{ElType}) where ElType
    # Scan the inputs for the ArrayAndChar:
    A = find_aac(bc)
    # Use the char field of A to create the output
    ArrayAndChar(similar(Array{ElType}, axes(bc)), A.char)
end

"`A = find_aac(As)` returns the first ArrayAndChar among the arguments."
find_aac(bc::Base.Broadcast.Broadcasted) = find_aac(bc.args)
find_aac(args::Tuple) = find_aac(find_aac(args[1]), Base.tail(args))
find_aac(x) = x
find_aac(::Tuple{}) = nothing
find_aac(a::ArrayAndChar, rest) = a
find_aac(::Any, rest) = find_aac(rest)

```

Broadcasting a custom function seems to work:

```julia
a = ArrayAndChar([1, 2, 3, 4], 'x')
func(x) = convert(UInt64, x)
d = func.(a)
println(d)
# outputs:
# ArrayAndChar{UInt64,1} UInt64[0x0000000000000001, 0x0000000000000002, 0x0000000000000003, 0x0000000000000004] with char 'x'

```

But if you make `func` take the type from the outer scope:

```julia
a = ArrayAndChar([1, 2, 3, 4], 'x')
tp = UInt64
func(x) = convert(tp, x)
d = func.(a)
println(d)

```

an error occurs in `Base.similar()`:

```julia
ERROR: LoadError: type Nothing has no field char

```

If you add `println(bc)` there, it’s easy to see why:

```julia
Base.Broadcast.Broadcasted{Base.Broadcast.ArrayStyle{ArrayAndChar}}(func, (Base.Broadcast.Extruded{ArrayAndChar{Int64,1},Tuple{Bool},Tuple{Int64}}(ArrayAndChar{Int64,1} [1, 2, 3, 4] with char 'x', (true,), (1,)),))

```

`ArrayAndChar` is encapsulated in `Base.Broadcast.Extruded` and is not picked up by `find_aac()`.

So, the question is: what’s happening here, and how do I cover all possible cases when defining broadcasting for a custom type? What other functions/methods should be defined? (Also, it feels like generalised versions of `find_aac()` and `Base.similar()` should be the default for this broadcast style…)

---

<div class="post-metadata">

**Author:** ![fjarri](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fjarri/32/630_2.png) [@fjarri](https://discourse.julialang.org/u/fjarri)\
**Post date:** [December 16, 2019, 1:12am UTC](https://discourse.julialang.org/t/defining-broadcast-for-custom-types-the-example-in-the-docs-fails/32291/2 "2019-12-16T01:12:01Z")

</div>

Seems to be solved by adding a method

```julia
find_aac(x::Base.Broadcast.Extruded) = x.x

```

Not sure why it is needed, or is it enough. Created a [PR](https://github.com/JuliaLang/julia/pull/34112).
