I was a little surprised today by the following behaviour:

julia> f(d=2) = d
f (generic function with 2 methods)

julia> f(a::Int) = -a
f (generic function with 3 methods)

julia> f()
-2

julia> methods(f)
# 3 methods for generic function "f":
f() at none:1
f(a::Int64) at none:1
f(d) at none:1

Yet, there is no bug here and Julia works as documented: the first 
definition creates two methods, with f() simply calling f(2). The result is 
-2 because I specified this is the behaviour I want f to have for integers. 
Still, it feels a bit weird that the value 2 is taken from the first 
definition above, but the corresponding method is not actually called - the 
second one is.

For completeness, the fact that the second definition is more specialized 
is not essential. The behaviour stays the same when you specialize d to be 
an Int as well:

julia> g(d::Int=2) = d
g (generic function with 2 methods)

julia> g(a::Int) = -a
g (generic function with 2 methods)

julia> g()
-2

julia> methods(g)
# 2 methods for generic function "g":
g() at none:1
g(a::Int64) at none:1

This time, there are only two methods for g and my second definition is 
called because it is given after the definition with d, essentially 
overwriting it. But the optional parameter survives this.

I guess that in my mind an optional parameter with a default value was tied 
to a specific method, but in a dynamic setting that is not necessarily the 
case. I don't think anything should change here (a warning at best, though 
that might be difficult), but it may be good to know about the above 
possibility when debugging code.


Reply via email to