# Manual dispatch over a constant type set

**URL:** <https://discourse.julialang.org/t/manual-dispatch-over-a-constant-type-set/57811>\
**Category:** Performance\
**Created:** [March 23, 2021, 6:18pm UTC](https://discourse.julialang.org/t/manual-dispatch-over-a-constant-type-set/57811 "2021-03-23T18:18:41Z")\
**Posts on this page:** 1\
**Showing post:** 4

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [March 23, 2021, 10:54pm UTC](https://discourse.julialang.org/t/manual-dispatch-over-a-constant-type-set/57811/4 "2021-03-23T22:54:21Z")

</div>

> [@RGon](#):
>
> I can’t add a new type parameter to x that contains the subclass, because the subclass can change.

Ah, ok, that certainly makes things harder. If that weren’t a constraint in your design, you might consider something like the way RigidBodyDynamics.jl represents different types of robot joints with a generic `Joint` type which has a specialized `JointType` type parameter: [https://github.com/JuliaRobotics/RigidBodyDynamics.jl/blob/0f42d2900174adc3c03911d217fd48a598c69bb8/src/joint.jl#L43-L47](https://github.com/JuliaRobotics/RigidBodyDynamics.jl/blob/0f42d2900174adc3c03911d217fd48a598c69bb8/src/joint.jl#L43-L47)

As for your `stream_dispatch`, I think the idea is workable, but you might be better served by a lisp-y tuple recursion style, rather than a generated function. The basic idea is something like this:

```julia
julia> foo(x::Int) = println("got an int")
foo (generic function with 1 method)

julia> foo(x::Float64) = println("got a float")
foo (generic function with 2 methods)

julia> function call_for_each(f, args)
         f(first(args)) # Do something with the first element
         call_for_each(f, Base.tail(args)) # Recurse with the rest
       end
call_for_each (generic function with 1 method)

julia> function call_for_each(f, args::Tuple{})  
         # Base case for our recursion when nothing is left
       end
call_for_each (generic function with 2 methods)

julia> call_for_each(foo, (1, 2.0, 3, 4, 5.0))
got an int
got a float
got an int
got an int
got a float

```

This kind of approach is type-stable because the compiler is smart enough to figure out the type of the `tail` of a tuple:

```julia
julia> @code_warntype call_for_each(foo, (1, 2.0, 3, 4, 5.0))
Variables
  #self#::Core.Compiler.Const(call_for_each, false)
  f::Core.Compiler.Const(foo, false)
  args::Tuple{Int64,Float64,Int64,Int64,Float64}

Body::Nothing
1 ─ %1 = Main.first(args)::Int64
│ (f)(%1)
│ %3 = Base.tail::Core.Compiler.Const(Base.tail, false)
│ %4 = (%3)(args)::Tuple{Float64,Int64,Int64,Float64}
│ %5 = Main.call_for_each(f, %4)::Core.Compiler.Const(nothing, false)
└── return %5

```

Note how the `(%3)(args)` has been inferred as a `Tuple{Float64, Int64, Int64, Float64}`, which is the type after the first element has been processed.

In your case, you have a tuple of types, and your `foo()` would be comparing the `.subclass` against each of those types, but I think the general idea could still work, and this completely avoids any need to worry about generated functions and the headaches they can create.

By the way, a totally different way to attack this problem would be to store `FunctionWrapper`s from FunctionWrappers.jl. Those are just a slightly nicer wrapper around function pointers, and they can allow you to do something more like virtual methods in C++, although they come with the same set of performance issues that virtual functions in C++ have. I’ve done that in a few cases, although I generally find it not to be worthwhile.

---

_[View the full topic](https://discourse.julialang.org/t/manual-dispatch-over-a-constant-type-set/57811)._
