# Dispatch on enum

**URL:** <https://discourse.julialang.org/t/dispatch-on-enum/77398>\
**Category:** General Usage\
**Tags:** multidispatch, enum\
**Created:** [March 4, 2022, 12:53pm UTC](https://discourse.julialang.org/t/dispatch-on-enum/77398 "2022-03-04T12:53:22Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Impressium](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/impressium/32/19575_2.png) [@Impressium](https://discourse.julialang.org/u/Impressium)\
**Post date:** [March 4, 2022, 12:53pm UTC](https://discourse.julialang.org/t/dispatch-on-enum/77398/1 "2022-03-04T12:53:22Z")

</div>

Hey all 🙂

Is it possible to dispatch a function on different enum instances.

Something like this:

```julia
julia> @enum E a b

julia> f(::Type{a}) = :a

julia> f(::Type{b}) = :b

julia> f(a)
:a

```

---

<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:** [March 4, 2022, 1:04pm UTC](https://discourse.julialang.org/t/dispatch-on-enum/77398/2 "2022-03-04T13:04:47Z")

</div>

use types.

---

<div class="post-metadata">

**Author:** ![jipolanco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jipolanco/32/12129_2.png) [@jipolanco](https://discourse.julialang.org/u/jipolanco)\
**Post date:** [March 4, 2022, 1:16pm UTC](https://discourse.julialang.org/t/dispatch-on-enum/77398/3 "2022-03-04T13:16:38Z")

</div>

You can get pretty close using value types:

```julia
julia> @enum E a b

julia> f(::Val{a}) = :a

julia> f(::Val{b}) = :b

julia> f(x::E) = f(Val(x))

julia> f(a)
:a

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 4, 2022, 1:31pm UTC](https://discourse.julialang.org/t/dispatch-on-enum/77398/4 "2022-03-04T13:31:32Z")

</div>

> [@jipolanco](#):
>
> `f(x::E) = f(Val(x))`

Note that this forces Julia to do a runtime dispatch in general (unless `x` is a compile-time constant), which is slow. Julia’s dispatch is really optimized for code in which the types are mostly inferred (constants) at compile time.

If you have runtime data in an `@enum`, you should probably be using `if` statements or similar, rather than dispatching on `Val`, or you should alternatively be re-thinking your code structure to put the information in the type domain to start with.

---

<div class="post-metadata">

**Author:** ![jipolanco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jipolanco/32/12129_2.png) [@jipolanco](https://discourse.julialang.org/u/jipolanco)\
**Post date:** [March 4, 2022, 1:39pm UTC](https://discourse.julialang.org/t/dispatch-on-enum/77398/5 "2022-03-04T13:39:27Z")

</div>

> [@stevengj](#):
>
> Note that this forces Julia to do a runtime dispatch in general (unless `x` is a compile-time constant), which is slow.

I totally agree, and I wouldn’t do what OP is asking myself. But it may still be convenient in some cases, and one might get away with constant propagation in the particular case the enum instances are treated as constants.

---

<div class="post-metadata">

**Author:** ![Impressium](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/impressium/32/19575_2.png) [@Impressium](https://discourse.julialang.org/u/Impressium)\
**Post date:** [March 4, 2022, 2:18pm UTC](https://discourse.julialang.org/t/dispatch-on-enum/77398/6 "2022-03-04T14:18:05Z")

</div>

That’s cool!

---

<div class="post-metadata">

**Author:** ![jw3126](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jw3126/32/3086_2.png) [@jw3126](https://discourse.julialang.org/u/jw3126)\
**Post date:** [March 4, 2022, 5:06pm UTC](https://discourse.julialang.org/t/dispatch-on-enum/77398/7 "2022-03-04T17:06:17Z")

</div>

IMO the key strength of multiple dispatch is **not** neat syntax like

```julia
f(::a) = ...
f(::b) = ...
f(::c) = ...

```

This syntax is nice to have but not essential to me.  
Instead the super power of multiple dispatch is openness.  
You can extend `YourLib.f(::MyType) ...` anywhere. This openness enables  
exceptional code reuse in julia, see also [this talk](https://www.youtube.com/watch?v=kc9HwsxE1OY).  
Now in case of enums, all instances are fixed, when the enum is defined.  
So there is no openness benefit of dispatch over good old `if` statements.  
So instead of

```julia
f(::a) = ...
f(::b) = ...
f(::c) = ...

```

I would recommend

```julia
function f(x::E)
    if x === a
        ...
    elseif x === b
        ...
    elseif x === c
        ...
    else
        error("Unreachable")
    end
end

```

It looks not as neat, but is equally powerful. If you really insist on the neat syntax I would use a macro to transform it into the `if else` chain.

---

<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:** [March 4, 2022, 5:17pm UTC](https://discourse.julialang.org/t/dispatch-on-enum/77398/8 "2022-03-04T17:17:40Z")

</div>

I agree with @jw3126, and I would like to add: if you want to use the multiple dispatch for openness, then you are better either using `Val{Symbol}` (simple but collision prone) or just define an abstract type `E` and let anyone to create subtypes to represent the values (even empty `struct A <: E; end` will work for dispatch). In fact, the abstract type is not even needed (as each user is supposed to write a method for their own concrete type) and `Any` could be used instead, but it may help debugging by restricting some generic methods to the abstract supertype (and catching when the user sends complete nonsense instead of their own struct-as-enum-value).
