3
votes

When I redefine a function that has been passed into another function, it seems the redefinition was not passed into that function.

 function foo(f)
        f(3)
    end

f(x)=x

foo(f) #=>3

f(x)=x*x

foo(f) #=>3

f(3) #=>9

This behavior looks so weird to me. What's the logic behind this?

1
Running f(x)=x*x prompts a definition overwritten warning. The warning alerts to the possibility of this kind of behavior. In general, redefining functions when some other functions referencing it have already been compiled is tricky. As github.com/julialang/julia/issues/265 from 2011 indicates, this is an old issue, but I guess programs can be refactored to avoid this issue. - Dan Getz
@DanGetz, you should just post that as an answer. - StefanKarpinski
It should also be mentioned that 265 was fixed in v0.6, so in a few weeks this will just be a non-issue for most users. Maybe an answer should make sure to say that? - Chris Rackauckas
"but I guess programs can be refactored to avoid this issue." just use anonymous functions. - Chris Rackauckas

1 Answers

5
votes

Running f(x)=x*x prompts a definition overwritten warning. The warning alerts to the possibility of this kind of behavior. In general, redefining functions when some other functions referencing it have already been compiled is tricky. As http://github.com/julialang/julia/issues/265 from 2011 indicates, this is an old issue.

A program can avoid this issue with care. For example, using anonymous functions with foo() in the question will give:

julia> foo(x->x)
3
julia> foo(x->x*x)
9

In Julia 0.6 this issue is resolved. The Github issue details the resolution, but essentially, Julia keeps track of a version number of the world, and a function 'sees' a certain version of the world. In the REPL, a redefinition causes the call to the older function to trigger a recompile (see http://docs.julialang.org/en/latest/manual/methods.html# for details). The resulting behavior is less weird:

julia> # version 6.0
julia> function foo(f)
       f(3)
       end
foo (generic function with 1 method)
julia> f(x)=x
f (generic function with 1 method)
julia> foo(f)
3
julia> f(x)=x*x
f (generic function with 1 method)    
julia> foo(f)
9
julia> # :-)

Thanks to @StefanKarpinski, @ChrisRackauckas