# Using multiple dispatch and the type system correctly

**URL:** <https://discourse.julialang.org/t/using-multiple-dispatch-and-the-type-system-correctly/61289>\
**Category:** New to Julia\
**Created:** [May 17, 2021, 9:40am UTC](https://discourse.julialang.org/t/using-multiple-dispatch-and-the-type-system-correctly/61289 "2021-05-17T09:40:23Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![DorianT](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/doriant/32/24897_2.png) [@DorianT](https://discourse.julialang.org/u/DorianT)\
**Post date:** [May 17, 2021, 9:40am UTC](https://discourse.julialang.org/t/using-multiple-dispatch-and-the-type-system-correctly/61289/1 "2021-05-17T09:40:24Z")

</div>

Hello everyone, I am currently trying to write a program using WebDriver.jl. My functions act on the ‘Element’ type of WebDriver ([WebDriver.jl/06\_Element.jl at master · Nosferican/WebDriver.jl · GitHub](https://github.com/Nosferican/WebDriver.jl/blob/master/src/01_structs/06_Element.jl)). I am mainly using two functions, one to identify the ‘Elements’ on the page I want to process and store their ‘id’ and ‘class’ in a dictionary, and another function that processes each element based on it’s class. I do, however, struggle with the latter. In a first test I simply used one function with multiple elseif blocks which did not even seem like a good idea on the first look (but was simple to deploy). It looks roughly like this:

```julia
if class_of_my_element == "exactly_this_class"
    do this
        elseif class_of_my_element == "exactly_this_other_class"
            do this
        elseif class_of_my_element == "exactly_this_other_third_class"
            do this

```

However, there is going to be a larger number of classes, and each of it will require a slightly different function to be called. Obviously I do not want to write 30 different functions with different names, but instead I would like to call the same function with different methods based on the class of each element. After reading up on the type system and multiple dispatch I still do not know how I could accomplish a clean solution in this case.

Can I create a subtype of ‘Element’ that has a field ‘class’ which requires a certain value? (This still means I am creating about 30 sub-types, but the work has to be done somewhere I believe). Or is it possible to use a dictionary to call different methods of a function based on a class =\> method mapping?

Really grateful for any input on how to approach this kind of problem.

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [May 17, 2021, 10:17am UTC](https://discourse.julialang.org/t/using-multiple-dispatch-and-the-type-system-correctly/61289/2 "2021-05-17T10:17:46Z")

</div>

This sounds like a use case for dispatching on a value: [Types · The Julia Language](https://docs.julialang.org/en/v1/manual/types/#%22Value-types%22)

Have you considered this? Of course the implementation differences need to be … well,… implemented.

---

<div class="post-metadata">

**Author:** ![ZettEff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zetteff/32/31976_2.png) [@ZettEff](https://discourse.julialang.org/u/ZettEff)\
**Post date:** [May 17, 2021, 11:24am UTC](https://discourse.julialang.org/t/using-multiple-dispatch-and-the-type-system-correctly/61289/3 "2021-05-17T11:24:34Z")

</div>

I would avoid using `if` to test for classes but instead write functions depending on types.

Something like this:

```julia
struct MyClass end
struct MyOtherClass end
...

# identify elements and map to class
function element_to_struct(el)
    if el == ... 
        return MyClass
    elseif ...
        return MyOtherClass
    ...
    end

end

# do something depending on which struct
function myfunc(el::MyClass)
     // do stuff
end

function myfunc(el::MyOtherClass)
     // do stuff
end

# Combine both
function main(el)
    cls = element_to_struct(el)
    return myfunc(cls)
end

```

Not sure if this approach is suitable for 30 different functions. Maybe there is a better way. But this would be my starting point.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [May 17, 2021, 11:38am UTC](https://discourse.julialang.org/t/using-multiple-dispatch-and-the-type-system-correctly/61289/4 "2021-05-17T11:38:46Z")

</div>

I am more or less saying the same thing as above, but is this the type of behavior you want?

```julia
julia> abstract type Class1 end

julia> abstract type Class2 end

julia> struct Type1 <: Class1 end

julia> struct Type2 <: Class2 end

julia> do_stuff(x::Class1) = "doing stuff with something of Class1"
do_stuff (generic function with 1 method)

julia> do_stuff(x::Class2) = "doing stuff with something of Class2"
do_stuff (generic function with 2 methods)

julia> x = Type1()
Type1()

julia> do_stuff(x)
"doing stuff with something of Class1"

julia> y = Type2()
Type2()

julia> do_stuff(y)
"doing stuff with something of Class2"

```

---

<div class="post-metadata">

**Author:** ![DorianT](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/doriant/32/24897_2.png) [@DorianT](https://discourse.julialang.org/u/DorianT)\
**Post date:** [May 17, 2021, 12:24pm UTC](https://discourse.julialang.org/t/using-multiple-dispatch-and-the-type-system-correctly/61289/6 "2021-05-17T12:24:53Z")

</div>

Thanks for all the suggestions. Dispatching on values seems helpful and it is my mistake that I have not realized it could be applied to my case when I read the docs. Thanks for pointing that out @oheil .

I can totally get behind the logic of @ZettEff s approach as this was very much along the lines of my initial thought, but I was lacking the concept of a helper function that maps the elements to certain classes first.

For the suggestions by @lmiq I am not sure if I understand it correctly, I am not yet sure why I would need Type1, Type2, etc. next to Class1, Class2, etc. but maybe I will realize that when I get deeper into the problem.

Thanks everyone for helping, I have a lot of ideas to work with now! 🙂

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [May 17, 2021, 12:28pm UTC](https://discourse.julialang.org/t/using-multiple-dispatch-and-the-type-system-correctly/61289/7 "2021-05-17T12:28:06Z")

</div>

> [@DorianT](#):
>
> I am not yet sure why I would need Type1, Type2, etc. next to Class1, Class2

Sorry, I am not sure either. I’ve shown that because the terminology “class” is usually associated with object-oriented programming, where types of “things” belong to different “classes”. The most similar construct in Julia (which is not object-oriented) is to define abstract types for the “classes” and, and types of variables (concrete types) which are subtypes of that abstract type. Then you can dispatch on the classes or on the concrete types, depending on the use case.

---

<div class="post-metadata">

**Author:** ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)\
**Post date:** [May 17, 2021, 12:35pm UTC](https://discourse.julialang.org/t/using-multiple-dispatch-and-the-type-system-correctly/61289/8 "2021-05-17T12:35:43Z")

</div>

You shouldn’t convert elements to structs in a single function, because it is literally going to be a type unstable function.

On a general note, this kind of task is complicated because it is basically runtime dispatch and runtime dispatch is slow. It’s a pity, but big fat `if` is the best solution from the performance point of view. You can use macros to avoid repetitive code to some degree. Also, if per-class functions are producing the same type (for example `Nothing`) then you can still use static multiple dispatch to some degree.

```julia
# do something depending on which struct
function myfunc(el::MyClass)
     // do stuff
end

function myfunc(el::MyOtherClass)
     // do stuff
end

# apply functions to classes
function action(f, el)
    if el == ... 
        return f(MyClass(el))
    elseif ...
        return f(MyOtherClass(el))
    ...
    end
end

# Usage
action(myfunc, el)

```

Definitely you shouldn’t put mapping to `Dict`, since it will introduce slowdown. You can use `NamedTuple` though, but it has it’s limits too.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [May 17, 2021, 12:41pm UTC](https://discourse.julialang.org/t/using-multiple-dispatch-and-the-type-system-correctly/61289/9 "2021-05-17T12:41:19Z")

</div>

> [@Skoffer](#):
>
> On a general note, this kind of task is complicated because it is basically runtime dispatch and runtime dispatch is slow.

@skoffer raises an important point, but it may be that the run time dispatch performance is not important for your application, and in this case you can choose the clearest and most extensible solution you want. In Julia we are somewhat obsessed with speed, but that is sometimes off the point.

---

<div class="post-metadata">

**Author:** ![ZettEff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zetteff/32/31976_2.png) [@ZettEff](https://discourse.julialang.org/u/ZettEff)\
**Post date:** [May 17, 2021, 1:02pm UTC](https://discourse.julialang.org/t/using-multiple-dispatch-and-the-type-system-correctly/61289/10 "2021-05-17T13:02:50Z")

</div>

Thanks for the argument on not converting elements to structs.

Could you explain what exactly is the problem with this approach in some more detail?

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [May 17, 2021, 1:08pm UTC](https://discourse.julialang.org/t/using-multiple-dispatch-and-the-type-system-correctly/61289/11 "2021-05-17T13:08:22Z")

</div>

This is one of the threads discussing that: [Performance drawback with subtyping - #6 by lmiq](https://discourse.julialang.org/t/performance-drawback-with-subtyping/51939/6)

and other threads are linked in that one. @skoffer usually post the best answers there (and I am struggling to understand what is going on the middle).

---

<div class="post-metadata">

**Author:** ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)\
**Post date:** [May 17, 2021, 1:46pm UTC](https://discourse.julialang.org/t/using-multiple-dispatch-and-the-type-system-correctly/61289/12 "2021-05-17T13:46:53Z")

</div>

Maybe this topic can be of interest: [How to work with type unstable functions?](https://discourse.julialang.org/t/how-to-work-with-type-unstable-functions/56389) I think it’s rather similar to what you are doing and it has some explanations.

---

<div class="post-metadata">

**Author:** ![ZettEff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zetteff/32/31976_2.png) [@ZettEff](https://discourse.julialang.org/u/ZettEff)\
**Post date:** [May 18, 2021, 5:01am UTC](https://discourse.julialang.org/t/using-multiple-dispatch-and-the-type-system-correctly/61289/13 "2021-05-18T05:01:08Z")

</div>

Thanks, very helpful.
