# Subtype or enum, which is prefer?

**URL:** <https://discourse.julialang.org/t/subtype-or-enum-which-is-prefer/65359>\
**Category:** General Usage\
**Tags:** question, enum\
**Created:** [July 27, 2021, 9:20am UTC](https://discourse.julialang.org/t/subtype-or-enum-which-is-prefer/65359 "2021-07-27T09:20:29Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![HaoxuanGuo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/haoxuanguo/32/19052_2.png) [@HaoxuanGuo](https://discourse.julialang.org/u/HaoxuanGuo)\
**Post date:** [July 27, 2021, 9:20am UTC](https://discourse.julialang.org/t/subtype-or-enum-which-is-prefer/65359/1 "2021-07-27T09:20:29Z")

</div>

```julia
abstract type AbstractFruit end
struct Apple <: AbstractFruit end
struct Banana <: AbstractFruit end
struct Pear <: AbstractFruit end

color(::Apple) = :red
color(::Banana) = :yellow
color(::Pear) = :green

```

and

```julia
@enum Fruit apple banana pear

color(fruit::Fruit) = 
     fruit == apple ? :red :
     fruit == banana ? :yellow :
     fruit == pear ? :green :
     :unknown

```

makes the simular function. In intuition, I think the first one is better. But when it is warpped in a struct or `Array`, the first one will cause type Union, which will be compile into pointers and cause performance problems.

Consider

```julia
AbstractFruit[Apple(), Banana(), Pear()] # which include 3 pointer
Fruit[apple, banana, pear] # which include 3 `Int32`

```

In this condition, is the enum better than the subtype?

---

<div class="post-metadata">

**Author:** ![tisztamo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tisztamo/32/16200_2.png) [@tisztamo](https://discourse.julialang.org/u/tisztamo)\
**Post date:** [July 27, 2021, 9:36am UTC](https://discourse.julialang.org/t/subtype-or-enum-which-is-prefer/65359/2 "2021-07-27T09:36:31Z")

</div>

It mostly depends on your needs: dynamism (e.g. adding new types in external packages) or performance.

Also, there are solutions to speed up the dispatch, if you really need the dynamism but wants to get some of the performance back.

For your example [SingleDispatchArrays.jl](https://github.com/melonedo/SingleDispatchArrays.jl) seems the best. I maintain a list of similar packages in the docs of Catwalk.jl: [Catwalk.jl Intro · Catwalk.jl](https://tisztamo.github.io/Catwalk.jl/dev/#Alternatives-1)

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [July 27, 2021, 10:30am UTC](https://discourse.julialang.org/t/subtype-or-enum-which-is-prefer/65359/3 "2021-07-27T10:30:21Z")

</div>

I’m wondering in which real-world use case multiple-dispatch would cause a significant performance problem.

To me, this is more of a design choice. If I’d like to take advantage of multiple-dispatch, subtyping is the only way. If the subtype is designed never to carry payloads in the future, I’d like to dispatch on the types instead of instances:

```julia
# dispatch on the types
abstract type AbstractFruit end
struct Apple <: AbstractFruit end
struct Banana <: AbstractFruit end
struct Pear <: AbstractFruit end

color(::Type{Apple}) = :red
color(::Type{Banana}) = :yellow
color(::Type{Pear}) = :green

```

```julia
# dispatch on the instances
abstract type AbstractFruit end
struct Apple <: AbstractFruit
    rotten::Bool # extra info to determine color
end
color(x::Apple) = x.rotten ? :black : :red

```

---

<div class="post-metadata">

**Author:** ![tisztamo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tisztamo/32/16200_2.png) [@tisztamo](https://discourse.julialang.org/u/tisztamo)\
**Post date:** [July 27, 2021, 11:03am UTC](https://discourse.julialang.org/t/subtype-or-enum-which-is-prefer/65359/4 "2021-07-27T11:03:05Z")

</div>

What is the benefit of dispatching on types?

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [July 27, 2021, 11:08am UTC](https://discourse.julialang.org/t/subtype-or-enum-which-is-prefer/65359/5 "2021-07-27T11:08:23Z")

</div>

Personally, I use this style to indicate any subtypes should never take any payloads.

In the case above, the original version of `color` only took an instance of certain `AbstractFruit` types.  
Then, I realized I need one more parameter, say `rotten`, to get the color of `Apple`. Without changing the interface of `color`, this new parameter(the payload) can be carried by the `Apple` type itself. This hack is not allowed if the `color` function is directly dispatched on the `Type{Apple}`.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [July 27, 2021, 11:47am UTC](https://discourse.julialang.org/t/subtype-or-enum-which-is-prefer/65359/6 "2021-07-27T11:47:58Z")

</div>

> [@Gnimuc](#):
>
> If the subtype is designed never to carry payloads in the future, I’d like to dispatch on the types instead of instances:

Looking at Base as an example, the dispatch is on `::Nothing` and `::Missing` not `::Type{Nothing}` and `::Type{Missing}`. Types also have various behavior such as not getting specialized on ([Performance Tips · The Julia Language](https://docs.julialang.org/en/v1/manual/performance-tips/#Be-aware-of-when-Julia-avoids-specializing)) etc. I would say using instances is in general preferable, even if you are not planning on bundling any data with it.

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [July 27, 2021, 1:10pm UTC](https://discourse.julialang.org/t/subtype-or-enum-which-is-prefer/65359/7 "2021-07-27T13:10:01Z")

</div>

What if I don’t care about the performance. 🙃

For years, I got addicted to making every piece of my Julia code type-stable. Why? Probably because Julia is advertised by its performance, a good Julia user should write decent code keeping in mind what the Performance Tips say. But then, I realized it’s a bit overkill to optimize everything, especially for something that is not performance-sensitive. Now, I just want to be a clueless Julia user and write Julia code without thinking too much.

> In intuition, I think the first one is better. But when it is warpped in a struct or `Array` , the first one will cause type Union, which will be compile into pointers and cause performance problems.

Now, if I hit something like this, I just follow intuition and I will follow my intuition on the dispatching-types- vs-dispatching-instances problem as well.

BTW, I did a check by running `(@which color(...)).specializations`, but the outputs were the same for the above examples. Am I missing something?

---

<div class="post-metadata">

**Author:** ![tisztamo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tisztamo/32/16200_2.png) [@tisztamo](https://discourse.julialang.org/u/tisztamo)\
**Post date:** [July 27, 2021, 2:07pm UTC](https://discourse.julialang.org/t/subtype-or-enum-which-is-prefer/65359/8 "2021-07-27T14:07:26Z")

</div>

> For years, I got addicted to making every piece of my Julia code type-stable. Why? Probably because Julia is advertised by its performance, a good Julia user should write decent code keeping in mind what the Performance Tips say.

Same here, only that I am in my second julian year, fully addicted. 🙂

I also thought that dispatching on types vs instances is mostly question of style (vaguely remember reading that somewhere about traits), and I personally find instance-based code easier to read, which is the main reason of my style choices. OTOH encoding things in style is something I also like to do. Still, I do not see why it is important to forbid subtypes having members.

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [July 27, 2021, 2:10pm UTC](https://discourse.julialang.org/t/subtype-or-enum-which-is-prefer/65359/9 "2021-07-27T14:10:47Z")

</div>

In fact, I use instances in most of the case except certain really simple cases like the example in OP. 😉
