# Dispatch on fields of my struct?

**URL:** https://discourse.julialang.org/t/dispatch-on-fields-of-my-struct/56054
**Category:** New to Julia
**Tags:** dispatch, value-types
**Created:** [February 25, 2021, 10:38pm UTC](https://discourse.julialang.org/t/dispatch-on-fields-of-my-struct/56054 "2021-02-25T22:38:48Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![marty0801](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marty0801/32/12715_2.png) [@marty0801](https://discourse.julialang.org/u/marty0801)
#### Post date: [February 25, 2021, 10:38pm UTC](https://discourse.julialang.org/t/dispatch-on-fields-of-my-struct/56054/1 "2021-02-25T22:38:48Z")

</div>

I’ve made a newbie mistake in constructing my types, and hoping for some good advice how to fix.

I two types, both containers having identical data layouts as below. I made them distinct because they represent different _ **concepts** _, and need to behave differently with my local methods.

```julia
struct A{T} 
    data::Vector{T} 
end 

struct B{T}
    data::Vector{T}
end 

func(a::A{T}) where {T}= ... 
func(b::B{T}) where {T}= ...

```

Only after constructing the types did I remember that they need to be recursive: `data` should be able to hold elements of either type `A` or `B`, e.g.

```julia
a= A([3]) 
b= B([4])
c= B([a,b]) 

```

which is impossible because the types are parametric. What should I do?

I see 2 options:

1. Replace `T` with `Any`, potentially incurring a performance hit.
2. Consolidate A and B under the same struct, but add another field to record their respective concepts as `Symbol`s, and then dispatch on that field using Value types, e.g.

```julia
struct C{T}
    data::Vector{T} 
    flavor::Symbol 
end 

```

where `flavor` can be `:A` or `:B`. But his requires to modify the methods, e.g.

```julia
func(c::C{T}) where {T}= func(c.flavor, c) 
func(::Var{:A}, c::C{T}) where {T}= ... 
func(::Var{:B}, c::C{T}) where {T}= ...

```

#1 is bad for performance; #2 feels a bit hacky, like I’m somehow evading Julia’s type-based dispatch system by instead trying to dispatch on fields.

Is there a third option? What would YOU DO? 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: [February 25, 2021, 10:50pm UTC](https://discourse.julialang.org/t/dispatch-on-fields-of-my-struct/56054/2 "2021-02-25T22:50:27Z")

</div>

```julia
julia> abstract type AorB{T} end

julia> struct A{T} <: AorB{T}
           data::Vector{T}
       end

julia> struct B{T} <: AorB{T}
           data::Vector{T}
       end

julia> a= A([3])
A{Int64}([3])

julia> b= B([4])
B{Int64}([4])

julia> c= B([a,b])
B{AorB{Int64}}(AorB{Int64}[A{Int64}([3]), B{Int64}([4])])

```

do they conceptually fit under the same Abstract type? So the `T` here would indicate what prime data type is internally used (think of `Complex{Float64}` vs. `Complex{Int64}`).

---

<div class="post-metadata">

### Author: ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)
#### Post date: [February 25, 2021, 10:57pm UTC](https://discourse.julialang.org/t/dispatch-on-fields-of-my-struct/56054/3 "2021-02-25T22:57:37Z")

</div>

The syntax here really trips me up. But this should be right.

```julia
julia> struct A{T}
       x::T
       end;

julia> struct B{T}
       x::T
       end;

julia> struct F{T<:Union{<:A, <:B}}
       x::Vector{T}
       end;

julia> function f(x::F{<:B})
       println("a F of B type")
       end;

julia> function f(x::F{<:A})
       println("a F of A type")
       end;

julia> fa = F([A(i) for i in 1:5])
F{A{Int64}}(A{Int64}[A{Int64}(1), A{Int64}(2), A{Int64}(3), A{Int64}(4), A{Int64}(5)])

julia> fb = F([B(i) for i in 1:5])
F{B{Int64}}(B{Int64}[B{Int64}(1), B{Int64}(2), B{Int64}(3), B{Int64}(4), B{Int64}(5)])

julia> f(fa)
a F of A type

julia> f(fb)
a F of B type

```

Please someone let me know if this is wrong!

---

<div class="post-metadata">

### Author: ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)
#### Post date: [February 26, 2021, 1:04am UTC](https://discourse.julialang.org/t/dispatch-on-fields-of-my-struct/56054/4 "2021-02-26T01:04:45Z")

</div>

I am not sure if I understood the problem, what is holding you back?

```julia
julia> struct A{T} 
           data::Vector{T} 
       end

julia> struct B{T}
           data::Vector{T}
       end 

julia> a = A([1, 2, 3])
A{Int64}([1, 2, 3])

julia> b = B([:a, :b, :c])
B{Symbol}([:a, :b, :c])

julia> c = A([a, b])
A{Any}(Any[A{Int64}([1, 2, 3]), B{Symbol}([:a, :b, :c])])

julia> c = A{Union{A, B}}([a, b])
A{Union{A, B}}(Union{A, B}[A{Int64}([1, 2, 3]), B{Symbol}([:a, :b, :c])])

julia> c = A{Union{A{Int64}, B{Symbol}}}([a, b])
A{Union{A{Int64}, B{Symbol}}}(Union{A{Int64}, B{Symbol}}[A{Int64}([1, 2, 3]), B{Symbol}([:a, :b, :c])])

```

You can define the structure with the types as tight as you want.

---

<div class="post-metadata">

### Author: ![marty0801](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marty0801/32/12715_2.png) [@marty0801](https://discourse.julialang.org/u/marty0801)
#### Post date: [February 26, 2021, 11:24am UTC](https://discourse.julialang.org/t/dispatch-on-fields-of-my-struct/56054/5 "2021-02-26T11:24:34Z")

</div>

@jling @Henrique_Becker Correct me if I’m wrong, but these seem to violate [one of the Julia performance tips](https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-abstract-container), which is the reason I rejected my option #1 above. I was hoping for a solution using only concrete types.

---

<div class="post-metadata">

### Author: ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)
#### Post date: [February 26, 2021, 12:15pm UTC](https://discourse.julialang.org/t/dispatch-on-fields-of-my-struct/56054/6 "2021-02-26T12:15:23Z")

</div>

You want a solution that uses only concrete types to having elements of two distinct types mixed inside a `Vector`? I do not believe this is possible. I do believe my solution (specially the one that fully specifies `A` and `B` types) at least benefits from the [union splitting optimization](https://julialang.org/blog/2018/08/union-splitting/).
