Search code examples
juliasymbolsdispatch

How do I do dispatch on value in julia?


I have heard julia has dispatch on values for symbols, and so I use Val{:MySymbol}.

But this doesn't seem to work:

julia> foo(x) = "other"
foo (generic function with 1 method)

julia> foo(x::Val{:zinger}) = "It was zinger"
foo (generic function with 2 methods)

julia> foo(:zinger)
"other"

Why isn't it outputting "It was zinger"?


Solution

  • See the Docs

    Dispatching on values isn't magic. It uses the exact same mechanics as for dispatching on parametric types. So you need to pass in a instance parametric type which has that value as a type parameter if you want to dispatch on it.

    In your question Val is the parametric type -- and it exists just for this kind of thing.

    So you need to have written:

    julia> foo(Val{:zinger}())
    "It was zinger"
    

    If you wanted you could write an overload of foo to automatically wrap up its arguments into a type parameter

    julia> foo(x::Symbol) = foo(Val{x}())
    foo (generic function with 3 methods)
    
    julia> foo(:zinger)
    "It was zinger"
    

    However, this will cause a dynamic dispatch.

    julia> @code_lowered foo(:zinger)
    CodeInfo(:(begin
            nothing
            return (Main.foo)(((Core.apply_type)(Main.Val, x))())
        end))
    

    vs the fully realized at compile-time solution:

    julia> @code_lowered foo(Val{:zinger}())
    CodeInfo(:(begin
            nothing
            return "It was zinger"
        end))