hello, I found myself got confused about multiple dispatch. Take the function rand as an example: there’re a lot of method definitions across different files:
rand(rng::AbstractRNG=GLOBAL_RNG, ::Type{X}=Float64) where {X} = rand(rng, Sampler(rng, X, Val(1)))
now I try to inspect which method definition is in use when calling rand(), which should give a random number in [0,1):
julia> @which rand()
rand() in Random at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v0.7/Random/src/Random.jl:222
seems like the above definition in Random.jl is in use. Now the questions are:
why the plain rand() definition in libc.jl (i.e. the first one) not called?
how do Julia decide the priority of the methods to dispatch if two or more methods all match the call? It could happen say one method has no parameter, and the other has parameters all having default values.
what does fun(::Type{X}=Float64) where {X} means? why could the parameter has no name?
Doesn’t really answer the question why the second is chosen:
julia> methods(Base.Libc.rand)
# 3 methods for generic function "rand":
[1] rand() in Base.Libc at libc.jl:374
[2] rand(::Type{UInt32}) in Base.Libc at libc.jl:376
[3] rand(::Type{Float64}) in Base.Libc at libc.jl:377
julia> methods(rand)
# 71 methods for generic function "rand":
...
[15] rand() in Random at C:\cygwin\home\Administrator\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.0\Random\src\Random.jl:222
...
Because that is what is being using in Main (i.e. the module of the REPL). In a module of yours you can choose which one you want:
julia> baremodule A
using Random: rand
Core.println(rand()) # uses Random.rand as at the REPL
end
0.25909
Main.A
julia> baremodule b
using Base.Libc: rand
Core.println(rand()) # uses Base.Libc.rand
end
1408058198
Main.b
could u be nice enough to point to where could I find the code of that using in module Main? (actually I don’t know which file corresponds to Main module).
it’s quite a way to define methods … (need to learn).
ah … so, there’s no such a file for module Main?
thus, having solved question 1, what about questions 2 and 3?
how do Julia decide the priority of the methods to dispatch if two or more methods all match the call? It could happen say one method has no parameter, and the other has parameters all having default values.
what does fun(::Type{X}=Float64) where {X} means? why could the parameter has no name ?
Note that rand is porbably one of the more complicated functions with respect to it’s distribution in source files. The reason is that although most random number stuff is in the Random stdlib rand itself is considered to be so essential that it has been decided to make it available in base julia.
could u please give me an example that throws “ambiguity error”? In the following, no error was thrown, and seems like the first method can never be used:
julia> function f()
println("000")
end
f (generic function with 1 method)
julia> function f(a=1)
println("111")
end
f (generic function with 2 methods)
julia> methods(f)
# 2 methods for generic function "f":
[1] f() in Main at none:2
[2] f(a) in Main at none:2
julia> f()
111
You should read Methods · The Julia Language, which indeed has such an example. If you make it through that section of the docs you’ll also find this and understand why the first method you define is not called.
however, the definition of f() = f(1) is duplicated, i.e. there was another defintion of f()already! The problem is it does not throw any error and the earlier definition is simply overrided?
as a simple test, I try the following:
julia> g() = 1
g (generic function with 1 method)
julia> g() = 2
g (generic function with 1 method)
and it’s the same: the redefinition of g()gave no error nor warning. Is it a desired behavior?
In practice redefinition never happens as one usually uses multiple dispatch with respect to all argument types. But redefinition is rather useful in interactive environments as REPL and Jupyter notebooks. So I see that as a desired behavior.
It does — as @mauro3 said above — for redefinitions inside packages (modules). The lesson from this is that one should develop code inside packages, using Revise.jl.
MethodError: f(::Int64, ::String) is ambiguous. Candidates:
f(x, y::String) in Main at In[15]:2
f(x::Int64, y) in Main at In[18]:1
Possible fix, define
f(::Int64, ::String)