8

I was wondering if there was a way to use Symbols for multiple dispatch, but also include a "catch-all method". i.e. something like

function dispatchtest{alg<:Symbol}(T::Type{Val{alg}})
  println("This is the generic dispatch. The algorithm is $alg")
end
function dispatchtest(T::Type{Val{:Euler}})
  println("This is for the Euler algorithm!")
end

The second one works and matches what's in the manual, I'm just wondering how you get the first one to work.

Chris Rackauckas
  • 18,645
  • 3
  • 50
  • 81
  • Is dispatch on elements `Val(alg)` (instead of types `Val{alg}`) of equal interest? – Moritz Schauer Sep 09 '18 at 08:40
  • 1
    This isn't of interest anymore. This was DiffEq's first design, but now we use types. These days I'd say it's best to use types since you are going to constrain the choices anyways to write the dispatches. If you do want to use Val, it's probably best to dispatch on the elements in v1.0 since constant prop will kick in an it'll be inferred. So this question is quite a relic of the past. – Chris Rackauckas Sep 09 '18 at 16:12

1 Answers1

9

You can do it this way:

julia> function dispatchtest{alg}(::Type{Val{alg}})
           println("This is the generic dispatch. The algorithm is $alg")
       end
dispatchtest (generic function with 1 method)

julia> dispatchtest(alg::Symbol) = dispatchtest(Val{alg})
dispatchtest (generic function with 2 methods)

julia> function dispatchtest(::Type{Val{:Euler}})
           println("This is for the Euler algorithm!")
       end
dispatchtest (generic function with 3 methods)

julia> dispatchtest(:Foo)
This is the generic dispatch. The algorithm is Foo

julia> dispatchtest(:Euler)
This is for the Euler algorithm!
HarmonicaMuse
  • 7,633
  • 37
  • 52
  • 1
    Note that the performance of this is likely to be less good than just having an if-else statement that checks for specific symbol values, and also slower than looking up symbols in a dictionary, so there's effectively no good use case for this. If you don't need extensibility, use if-else; if you do need extensibility, use a dict. – StefanKarpinski Sep 06 '16 at 16:47
  • Could you please provide us with a good use case for value types then? Chris does need the extensibility. Do you mean to use a global Dict instead? That could be a problem with precompilation if I understand correctly. – HarmonicaMuse Sep 06 '16 at 19:21
  • 1
    How it effects performance really depends on how costly the function is. In my case, the functions are very costly and would it the if-else statement thousands if not tens of thousands of times, where else the price of dispatch is payed once (and it minuscule, measured probably in microseconds in comparison to the minutes / hours of the actual function call). I've found this solution as really helping performance in this case. As always, benchmark for your specific case. – Chris Rackauckas Oct 03 '16 at 06:28
  • 1
    @StefanKarpinski `if-else` is the recommended approach to define `getproperty` for custom types? Will the branching be elided at compile time (since the compiler knows in principle which symbol was actually used)? – a06e Oct 03 '18 at 21:50
  • Stumbled across this now (years after, v1.9.2), and this was useful. Just to point out that first line "function dispatchtest{alg}(::Type{Val{alg}})" should be changed to "function dispatchtest(::Type{Val{alg}}) where alg" or similar to work. – TheWhitestOfFangs Aug 24 '23 at 02:01