Reputation: 2697
In this short sequence, the user creates a function userfunc()
, but then wants to update the first definition to do something different. However the programfunc()
has already compiled the first version, and continues to use it.
userfunc(str, n) = str ^ n
userfunc("hello", 3)
"hellohellohello"
# program makes use of the user's function
programfunc(func, a, b) = func(a, b)
programfunc(userfunc, "hello", 3)
"hellohellohello"
# now the user redefines the function
userfunc(str, n) = str ^ (n * n)
# userfunc("hello", 3) give "hellohellohellohellohellohellohellohellohello"
# but program still makes use of the first userfunc()
programfunc(userfunc, "hello", 3)
"hellohellohello"
So how could programfunc()
be defined so that it always uses the latest definition of the function passed to it?
Upvotes: 3
Views: 119
Reputation: 28202
invoke
will do it. (Note though this will probably not compile to nice specialized code)
The issue here is that julia specialized on Type. That is to say it compiles a custom version of the function for every combination of types passed to it. Since Functions have a type in julia 0.5 (Each function is a singleton type.) that causes it to specialize on the function
tested on 0.5-rc0
julia> userfunc(str, n) = str ^ (n*n)
WARNING: Method definition userfunc(Any, Any) in module Main at REPL[16]:1 overwritten at REPL[20]:1.
userfunc (generic function with 1 method)
julia> function programfunc(func, a, b)
invoke(func, (typeof(a), typeof(b)), a, b)
end
programfunc (generic function with 1 method)
julia> programfunc(userfunc, "hello", 3)
"hellohellohellohellohellohellohellohellohello"
julia> userfunc(str, n) = str ^ (n)
WARNING: Method definition userfunc(Any, Any) in module Main at REPL[16]:1 overwritten at REPL[20]:1.
userfunc (generic function with 1 method)
julia> programfunc(userfunc, "hello", 3)
"hellohellohello"
Note this also works around #265
julia> foo(x)=2*x
foo (generic function with 1 method)
julia> function g(x)
invoke(foo, (typeof(x),), x)
end
g (generic function with 1 method)
julia> g(2)
4
julia> foo(x)=3*x
WARNING: Method definition foo(Any) in module Main at REPL[1]:1 overwritten at REPL[10]:1.
foo (generic function with 1 method)
julia> g(2)
6
Upvotes: 3
Reputation: 5325
A simple workaround is to use an anonymous function:
programfunc((x,y) -> userfunc(x,y), "hello", 3)
This works because a new anonymous function is created each time:
julia> f(x) = x
x -> f (generic function with 1 method)
julia> x -> f(x)
(::#15) (generic function with 1 method)
julia> x -> f(x)
(::#17) (generic function with 1 method)
Upvotes: 3