Here's what looks to me the simplest imaginable example of multiple dispatch in Julia - it's the entire (8 line) contents of a file called adhoc.jl.
f = function(x::String)
println("Called first version of f")
end
f = function(x::Float64)
println("Called second version of f")
end
f("x")
f(1.0)
and yet when I run that (via include("Adhoc.jl")
) julia complains:
ERROR: LoadError: MethodError: no method matching
(::getfield(Main, Symbol("##17#18")))(::String)
With screenshot here
If I change that second instance of f
to g
things work, but that's no longer making use of multiple dispatch. How come I can't get to first base with multiple dispatch?
Using all of a function's arguments to choose which method should be invoked, rather than just the first, is known as multiple dispatch.
Multiple dispatch is a way that we can apply function calls as properties of types. In other words, we can redefine the same function over and over again, but just plan for different types to be passed through it in order to essentially recreate the method to handle a new type. Consider the following example.
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.
Macros change existing source code or generate entirely new code. They are not some kind of more powerful function that unlocks secret abilities of Julia, they are just a way to automatically write code that you could have written out by hand anyway.
This is the corrected version:
function f(x::String)
println("Called first version of f")
end
function f(x::Float64)
println("Called second version of f")
end
f("x")
f(1.0)
The problem with your code is that your original code created an anonymous function and assigned it to a variable f
. And you did it twice, thus f
pointed only at function(x::Float64)
.
You can see the problem with your original code by running it in Julia REPL:
julia> f = function(x::String)
println("Called first version of f")
end
#3 (generic function with 1 method)
julia> f = function(x::Float64)
println("Called second version of f")
end
#5 (generic function with 1 method)
julia> methods(f)
# 1 method for generic function "#5":
[1] (::getfield(Main, Symbol("##5#6")))(x::Float64) in Main at REPL[2]:2
and you see that f
points at an anonymous function which has only one method.
Running my code (you need to restart Julia REPL as f
variable name will be already taken and it cannot be reassigned):
julia> function f(x::String)
println("Called first version of f")
end
f (generic function with 1 method)
julia> function f(x::Float64)
println("Called second version of f")
end
f (generic function with 2 methods)
julia> f("x")
Called first version of f
julia> f(1.0)
Called second version of f
julia> methods(f)
# 2 methods for generic function "f":
[1] f(x::Float64) in Main at REPL[2]:2
[2] f(x::String) in Main at REPL[1]:2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With