I was playing around with map and encountered some unexpected behaviour when changing the definition of the argument function.
Define a function
julia> f(x) = x + 2
f (generic function with 1 method)
Apply map to the function and a collection.
julia> map(f,1:3)
3-element Array{Int64,1}:
 3
 4
 5
Redefine f
f(x) = x + 3
WARNING: Method definition f(Any) in module Main at REPL[1]:1 overwritten at REPL[3]:1.
f (generic function with 1 method)
Apply map to redefined f and the same collection.
julia> map(f,1:3)
3-element Array{Int64,1}:
 3
 4
 5
Hmmm. Looks like f never changed. Collect the collection.
map(f,collect(1:3))
3-element Array{Int64,1}:
 4
 5
 6
Oh, now it changed. Change f one more time.
f(x) = x + 4
WARNING: Method definition f(Any) in module Main at REPL[3]:1 overwritten at REPL[13]:1.
f (generic function with 1 method)
Apply map to f and the collected collection.
map(f,collect(1:3))
3-element Array{Int64,1}:
 4
 5
 6
It’s still using the previous definition of f. Well then.
I expected map to use the current definition of f, so if I change f and call map again same arguments as before, map would use the new definition of f, much like changing the second argument to map changes the collection that f gets applied to. But instead, it looks like map is using the definition of f from when map was first called.
This is not the kind of behaviour I would infer from the documentation which states simply that map(f,c...) “transform[s] collection c by applying f to each element.” I spent a while reading other documentation on functions to find the answer, but didn’t see anything describing or explaining this kind of behaviour.
I can get around this by writing map(x->f(x),r), but that seems rather roundabout.
Is this behaviour on purpose? Is there a better way to work around it?