# How to dispatch by value?

**URL:** <https://discourse.julialang.org/t/how-to-dispatch-by-value/43266>\
**Category:** New to Julia\
**Created:** [July 17, 2020, 10:26pm UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266 "2020-07-17T22:26:35Z")\
**Posts on this page:** 6\
**Page:** 2

<div class="post-metadata">

**Author:** ![Bryan\_So](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bryan_so/32/16228_2.png) [@Bryan\_So](https://discourse.julialang.org/u/Bryan_So)\
**Post date:** [July 18, 2020, 5:18pm UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/21 "2020-07-18T17:18:24Z")

</div>

It’s fair to ask for the intended use case. Here it is. It’s a language interpreter.

```julia
struct Expr
    id, data
end

```

id is a hundred or so symbols, say :integer, :string, :+, :-, :\*, 😕 …that is a hundred or so language “lexicons” (I meant to type :slash but it rendered as an frowning icon)

data can be very simple if it is atomic like a number: Expr(:number, 123.4)

or can be recursive, e.g. for addition we will have Expr(:+, )

`Expr(:+, (Expr(:integer, 1), Expr(:integer, 2)))`

Now to display an Expr as a string we may define a string function:

```julia
function Base.string(x::Expr)
    if x.id == :integer 
        string(x.data)
    elseif x.id == :something_else
        do_something_else(x.data)
    elseif ..
    ... hundreds of these...
end

```

I am no longer opposed to doing

```julia
Expr_number <: Expr
Expr_add <: Expr 
Expr_subtract <: Expr
...
Base.string(x::Expr_number) = ...
Base.string(x::Expr_add) = ...
Base.string(x::Expr_subtract) = ...

```

It’s nice this way each operation can be kept in its own file.

Is it worthwhile to have a few hundred subtypes as opposed to one Expr where id tells me the operation? To avoid a hundred if…then branches?

---

<div class="post-metadata">

**Author:** ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)\
**Post date:** [July 18, 2020, 6:15pm UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/22 "2020-07-18T18:15:07Z")

</div>

As the conditions seem to be mutually exclusive, you can try to define a global to build the resulting function AST, then modify it within other files by adding more branches and finally `eval` it.

Edit:  
Or just define a dispatch table as a `Dict{Symbol, Any}`?  
Then it will be

```julia
p(c::Structure) = DISPATCH_TABLE[c.id](c.data)

```

---

<div class="post-metadata">

**Author:** ![Bryan\_So](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bryan_so/32/16228_2.png) [@Bryan\_So](https://discourse.julialang.org/u/Bryan_So)\
**Post date:** [July 18, 2020, 7:01pm UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/23 "2020-07-18T19:01:56Z")

</div>

Posted another topic to understand the combinatorial explosion issue:

> [@Understanding the dangers of abusing multiple dispatch](https://discourse.julialang.org/t/understanding-the-dangers-of-abusing-multiple-dispatch/43301):
>
> Hi, I’d like to understand more about this topic: The dangers of abusing multiple dispatch [https://docs.julialang.org/en/v1.6-dev/manual/performance-tips/#The-dangers-of-abusing-multiple-dispatch-(aka,-more-on-types-with-values-as-parameters)-1](https://docs.julialang.org/en/v1.6-dev/manual/performance-tips/#The-dangers-of-abusing-multiple-dispatch-(aka,-more-on-types-with-values-as-parameters)-1) I don’t understand when we will get combinatorial explosion, quote For example, you might imagine using it to store information, e.g. struct Car{Make, Model} year::Int ...more fields... end and then dispatch on objects like Car{:Honda,:A…

Thx

---

<div class="post-metadata">

**Author:** ![marius311](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marius311/32/3953_2.png) [@marius311](https://discourse.julialang.org/u/marius311)\
**Post date:** [July 18, 2020, 10:34pm UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/24 "2020-07-18T22:34:46Z")

</div>

The thing you’re trying to do here is basically what often goes under the name “traits” in Julia. There’s several different packages which facilitate this. Under the hood they basically do something equivalent to @xiaodai’s `Val` code above, so there’s no getting around the performance issues being discussed, but if performance is not critical, traits can certainly offer a nice syntax / logical organization / allow you or your users to add new cases in a way that would be impossible with a big if-statement.

For example, using [https://github.com/schlichtanders/Traits.jl](https://github.com/schlichtanders/Traits.jl) you can do exactly your original desired syntax:

```julia
using Traits

struct Structure
    id
end

@traits function p(c::Structure) where {c.id == :x}
    "c.id is x"
end
@traits function p(c::Structure) where {c.id == :y}
    "c.id is y"
end

julia> p(Structure(:x))
"c.id is x"

julia> p(Structure(:y))
"c.id is y"

julia> p(Structure(:z))
ERROR: MethodError: no method matching p(...)

```

The nice thing is that the final thing is a MethodError as you might expect, and you’re free to implement it later if you’d like.

---

<div class="post-metadata">

**Author:** ![Bryan\_So](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bryan_so/32/16228_2.png) [@Bryan\_So](https://discourse.julialang.org/u/Bryan_So)\
**Post date:** [July 19, 2020, 4:56am UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/25 "2020-07-19T04:56:08Z")

</div>

> [@marius311](#):
>
> The thing you’re trying to do here is basically what often goes under the name “traits” in Julia.

Amazing. Thanks

---

<div class="post-metadata">

**Author:** ![JeffFessler](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jefffessler/32/6650_2.png) [@JeffFessler](https://discourse.julialang.org/u/JeffFessler)\
**Post date:** [July 28, 2021, 12:05pm UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/26 "2021-07-28T12:05:15Z")

</div>

> [@hendri54](#):
>
> Parametric types would be one solution:
> 
> ```julia
> 
> ```

Despite the manual warning against over-use of types with values as parameters, it is worth noting (for others searching for this topic) that Julia itself does exactly that for 7 different ways of rounding:

> <https://github.com/JuliaLang/julia/blob/1b93d53fc4bb59350ada898038ed4de2994cce33/base/rounding.jl#L52>

Presumably the benefit there of dispatch over if/elseif is the extensibility.  
It’s a clean example for anyone wanting to essentially dispatch on a few Symbols.

[Previous page](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266.md?page=1)
