# 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:** 20\
**Page:** 1

<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 17, 2020, 10:26pm UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/1 "2020-07-17T22:26:35Z")

</div>

Very beginner question about using “where” in function declaration.

Is it possible to do something like this?

```julia
function p(c::Structure) where c.id == :x   
    do something now I know c.id == :x
end
function p(c::Structure) where c.id == :y 
    do something now I know c.id == :y
end

```

Of course I did try and no it can’t be done… so basically asking what can be done to emulate multiple dispatch by value.

The following is obvious and trivial BUT I’d like to modularize by putting each function f in its own file, which can’t be done by this monolithic approach.

```julia
function p(c::Struct)
    if c.id == :x 
        do something
    elseif c.id == :y
        do something else
    end
end

```

Defining Structure as abstract, and have subtypes like

```julia
StructureX <: Structure
StructureY <: Structure
...

```

will need a lot of such subtypes in my intended use case.

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [July 17, 2020, 10:36pm UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/2 "2020-07-17T22:36:09Z")

</div>

Parametric types would be one solution:

```julia
julia> struct Foo{T} end

julia> f1=Foo{1}()
Foo{1}()

julia> function use_foo(f :: Foo{1}); println("1"); end
use_foo (generic function with 1 method)

julia> function use_foo(f :: Foo{2}); println("2"); end
use_foo (generic function with 2 methods)

julia> use_foo(f1)
1

```

---

<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 17, 2020, 10:48pm UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/3 "2020-07-17T22:48:46Z")

</div>

Probably, the already mentioned solution of parameterizing `Structure`, so that the symbol goes to the type signature, is “the best” for this case:

```julia
p(c::Structure{:x}) = ⟨code for x⟩
p(c::Structure{:y}) = ⟨code for y⟩

```

But that approach is not recommended unless the options, for the most part, can be resolved at compile time(see [Performance Tips · The Julia Language](https://docs.julialang.org/en/v1/manual/performance-tips/#The-dangers-of-abusing-multiple-dispatch-(aka,-more-on-types-with-values-as-parameters)-1)).

---

<div class="post-metadata">

**Author:** ![xiaodai](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xiaodai/32/15937_2.png) [@xiaodai](https://discourse.julialang.org/u/xiaodai)\
**Post date:** [July 17, 2020, 11:24pm UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/4 "2020-07-17T23:24:57Z")

</div>

If `Structure` is already defined then this would work too

```julia
# using multiple dispatch
function p(::Structure)
  p(Val(c.id))
end

p(::Val{:x}) = "it is :x"

p(::Val{:y}) = "it is :y"

```

The potential reservation I have is I do not know how performant it is. I heard that sometimes dispatching on `Val` is “slow”.

---

<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, 12:46am UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/5 "2020-07-18T00:46:20Z")

</div>

Thanks for all the replies. May I ask how bad the performance is?

e.g.

```julia
struct Expr{id} end

f(c::Expr{:a}) = println("a")

f(c::Expr{:b}) = println("b")
... say 100 of them ...

f(x)

```

If it f(x) cannot be determined at compile time, the worst is a linear search, no more worse than the monolithic if…elseif… right? Such as

```julia
if id == :a 
    do this
elseif id == :b
    do that
... 100 of these ...

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [July 18, 2020, 12:54am UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/6 "2020-07-18T00:54:31Z")

</div>

It will be much worse in the constant factor. If you have a branch, you should just use a branch. You shouldn’t use dispatch just because you want to use it…

---

<div class="post-metadata">

**Author:** ![xiaodai](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xiaodai/32/15937_2.png) [@xiaodai](https://discourse.julialang.org/u/xiaodai)\
**Post date:** [July 18, 2020, 1:24am UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/7 "2020-07-18T01:24:46Z")

</div>

You can use BenchmarkTools.jl

```julia
using BenchmarkTools

@benchmark f(c)

```

---

<div class="post-metadata">

**Author:** ![robsmith11](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/robsmith11/32/29641_2.png) [@robsmith11](https://discourse.julialang.org/u/robsmith11)\
**Post date:** [July 18, 2020, 4:20am UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/8 "2020-07-18T04:20:30Z")

</div>

Are you referring to extra compile time or is there another reason why using dispatch to branch would be slower?

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [July 18, 2020, 4:23am UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/9 "2020-07-18T04:23:12Z")

</div>

If the dispatch happens at runtime (which it often will if you’re dispatching on a dynamic value), it can easily be on the order of milliseconds.

---

<div class="post-metadata">

**Author:** ![robsmith11](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/robsmith11/32/29641_2.png) [@robsmith11](https://discourse.julialang.org/u/robsmith11)\
**Post date:** [July 18, 2020, 5:09am UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/10 "2020-07-18T05:09:49Z")

</div>

Could you give an example of how it could take milliseconds?

There seems to be no overhead with a trivial example:

```julia
julia> struct S{T}
       end

julia> f(x::S{1}) = true
f (generic function with 1 method)

julia> f(x::S{2}) = false
f (generic function with 2 methods)

julia> @btime f(S{1}())
  0.020 ns (0 allocations: 0 bytes)
true

julia> @btime f(S{2}())
  0.020 ns (0 allocations: 0 bytes)
false

```

EDIT:  
I guess that’s too trivial. I do see the difference here:

```julia
julia> g(x) = x == 1
g (generic function with 1 method)

julia> @btime f(S{rand(1:2)}())
  175.926 ns (0 allocations: 0 bytes)
false

julia> @btime g(rand(1:2))
  7.090 ns (0 allocations: 0 bytes)
true

```

Not milliseconds, but significant. What’s the cause of the difference?

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [July 18, 2020, 5:19am UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/11 "2020-07-18T05:19:41Z")

</div>

If you instead time it with `@btime f(S{rand(Bool) + 1}())`, it goes up to 3 microseconds. More complicated (multivariable or more methods) can get exponentially harder.

---

<div class="post-metadata">

**Author:** ![robsmith11](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/robsmith11/32/29641_2.png) [@robsmith11](https://discourse.julialang.org/u/robsmith11)\
**Post date:** [July 18, 2020, 5:27am UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/12 "2020-07-18T05:27:25Z")

</div>

Is there anyway to see what’s causing the overhead? `@code_native` doesn’t seem to show the calculations done for type parameters:

```julia
julia> @btime f(S{rand(Bool) + 1}())
  169.373 ns (0 allocations: 0 bytes)
false

julia> @code_native f(S{rand(Bool) + 1}())
        .text
; ┌ @ REPL[2]:1 within `f'
        movb $1, %al
        retq
        nopw %cs:(%rax,%rax)
; └

```

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [July 18, 2020, 5:29am UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/13 "2020-07-18T05:29:26Z")

</div>

What’s causing the overhead is picking which function to run, not running the function itself. The slow part is method ordering stuff way deep in base Julia that is in the worst case exponential in the number of arguments (although there are faster paths).

---

<div class="post-metadata">

**Author:** ![robsmith11](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/robsmith11/32/29641_2.png) [@robsmith11](https://discourse.julialang.org/u/robsmith11)\
**Post date:** [July 18, 2020, 5:39am UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/14 "2020-07-18T05:39:48Z")

</div>

Thanks. That makes sense. I found some further discussion here:  
[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)

EDIT: Should have read the thread more carefully. That link has already been helpfully posted. Sorry for the noise.

---

<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, 6:05am UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/15 "2020-07-18T06:05:49Z")

</div>

Oscar,

Exponential is like 2^n, much worse than say n^3

It doesn’t “feel” like this type of algorithm needs exponential time to achieve. But I am no expert. Just a gut feeling.

---

<div class="post-metadata">

**Author:** ![johnmyleswhite](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnmyleswhite/32/31_2.png) [@johnmyleswhite](https://discourse.julialang.org/u/johnmyleswhite)\
**Post date:** [July 18, 2020, 10:06am UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/16 "2020-07-18T10:06:10Z")

</div>

If you have K types and N arguments, you have K^N possible type tuples, no?

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [July 18, 2020, 11:20am UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/17 "2020-07-18T11:20:09Z")

</div>

I have a feeling that the discussion is losing track of the original question.

The OP required that the methods that handle each case should be in different files. (Why?) That would seem to rule out the obvious `if ... elseif` approach.

Figuring out the optimal approach then requires a bit more information.

- How many distinct values for `id` are there?
- Is dispatch performance likely a big deal or not? I.e., does the “do something” part take a long time or not?
- Should a user be able to extend the set of `id` values. Or can that be hard-wired in a single function (as in the `if ... elseif` case)?
- Is the value of `id` set in a way that allows the compiler to infer, say, a parametric type? Or is it, say, loaded from a file and therefore dynamic dispatch is inevitable?

I think it will be hard to give useful advice without this information.

The OP dislikes the option of defining concrete sub-types for each `id` value. I wonder why. Given that a separate method needs to be written for each `id`, adding one line that defines a `StructureX` concrete type would seem to add little work.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [July 18, 2020, 1:21pm UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/18 "2020-07-18T13:21:14Z")

</div>

> [@hendri54](#):
>
> The OP required that the methods that handle each case should be in different files. (Why?) That would seem to rule out the obvious `if ... elseif` approach.

No. It’s perfectly fine to call other functions in the branch.

---

<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:01pm UTC](https://discourse.julialang.org/t/how-to-dispatch-by-value/43266/19 "2020-07-18T17:01:00Z")

</div>

> If you have K types and N arguments, you have K^N possible type tuples, no?

I’d like to start another thread to discuss this. This is very interesting. But Hendri54 was right. This is a sidetrack from original question. I’ll answer Hendri54 next.

---

<div class="post-metadata">

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

</div>

Sorry I was very unclear. I was assuming that the files were not available to be simply included when the dispatch function is compiled (either because the set of `id`s is not known ex ante or because they are in a different module written later). But perhaps I am reading too much between the lines.

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