Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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"?

like image 740
Lyndon White Avatar asked Jul 28 '18 04:07

Lyndon White


People also ask

What is multiple dispatch in Julia?

Using all of a function's arguments to choose which method should be invoked, rather than just the first, is known as multiple dispatch.

What is Julia exclamation mark?

an exclamation mark is a prefix operator for logical negation ("not") a! function names that end with an exclamation mark modify one or more of their arguments by convention.

Does Julia have methods?

Method TablesEvery function in Julia is a generic function. A generic function is conceptually a single function, but consists of many definitions, or methods. The methods of a generic function are stored in a method table.

How is multiple dispatch different from method overloading?

Method overloading is resolved at compile time. Multiple dispatch is resolved at runtime. When using double dispatch the called method depends on the actual type of receiver and arguments. Method overloading however, only allows the called method to depend on the declared type of the parameters.


1 Answers

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))
like image 190
Lyndon White Avatar answered Nov 26 '22 15:11

Lyndon White