Hi,
Is it possible to override a method with a closure?
function add(x, y) x + y end
function test()
add(y) = add(1, y)
add(2)
end
test()
ERROR: MethodError: no method matching (::var"#add#4")(::Int64, ::Int64)
The same thing happens if I define add as function add(y) add(1, y) end
, and it doesn’t seem to help if I declare global add
as the first line of test. Is this possible, or do I just need to use different names?
Thanks in advance!
Hi and welcome!
The definition of add
as a local name shadows all outer definitions.
To access any global identifier within a scope where that name is already taken, you can prepend them with the module name.
In your case, assuming you work in module Main:
function add(x, y) x + y end
function test()
add(y) = Main.add(1, y)
add(2)
end
test()
2 Likes
Thanks!
That makes sense. In this instance it would be nice if local identifiers could overload ones from outer scopes, but I imagine that the trade-offs around default cases for scopes are fairly tricky.
This implies that there’s still no overloading happening?
That is, if I wish to use the outer add
in test()
the only options are either add(x, y) = Main.add(x, y)
or Main.add(3, 4)
? There’s no automatic way of having the inner add
include all the overloads of the outer one?
(There’s no problem with this, I can just rename things or use Main
. Just wanting to make sure I understand)
Thanks!
Right, there’s no overloading.
The problem here is that local add
and Main.add
are two different identifiers. So, the local add
cannot possibly add overloaded behavior to Main.add
within local context.
The local add
, however, can be overloaded:
function add(x, y) x + y end
function test()
add(x, y) = Main.add(x, y)
add(y) = add(1, y)
add(y::Nothing) = 1
return add(2), add(nothing)
end
test() # returns (3, 1)
2 Likes
I’m not sure what you want to achieve, but overloading a local function can be a way to build a function with multiple methods closing over some local state. For example:
function make_inc()
c = Ref(0)
inc(n) = c[]+=n
inc() = inc(1)
inc
end
julia> const inc = make_inc()
inc (generic function with 2 methods)
julia> inc()
1
julia> inc()
2
julia> inc(3)
5
2 Likes
Thanks, but not in this case. The use case is really just readability:
function helper(p1, p2, p3, v1, v2) ... end
function doer(p1, p2, p3)
helper(v1, v2) = Main.helper(p1, p2, p3, v1, v2)
helper(va, vb)
helper(vc, vd)
...
end
(In retrospect, I probably should have put that in the first post)