Helps to expand the expressions, so I'll modify your code a bit. It's long so uncollapse and collapse this.
julia> exprs = Expr[]
Expr[]
julia> for (t, op) in zip((:Int, :Float64),(:f1, :f2))
print(t, " ", op, "\n")
push!(exprs, :(begin
f3($op) = begin
println($t)
println($op)
x -> $t($op(x) + 3)
end
end))
end
Int f1
Float64 f2
julia> exprs[1]
quote
#= REPL[24]:4 =#
f3(f1) = begin
#= REPL[24]:4 =#
#= REPL[24]:5 =#
println(Int)
#= REPL[24]:6 =#
println(f1)
#= REPL[24]:7 =#
x->begin
#= REPL[24]:7 =#
Int(f1(x) + 3)
end
end
end
julia> exprs[2]
quote
#= REPL[24]:4 =#
f3(f2) = begin
#= REPL[24]:4 =#
#= REPL[24]:5 =#
println(Float64)
#= REPL[24]:6 =#
println(f2)
#= REPL[24]:7 =#
x->begin
#= REPL[24]:7 =#
Float64(f2(x) + 3)
end
end
end
The two function definition’s headers were f3(f1) and f3(f2). Those are the same method signatures with local argument names that masks unrelated global functions, so the second one overrode the first one. You likely intended to dispatch on the functions f1 and f2, so the headers should be f3(::typeof(f1)) and f3(::typeof(f2)).
Full fix
for (t, op) in zip((:Int, :Float64),(:f1, :f2))
print(t, " ", op, "\n")
@eval begin
f3(::typeof($op)) = begin
println($t)
println($op)
x -> $t($op(x) + 3)
end
end
end
One way you can check for mistaken overwriting is methods(f3), it’ll list the headers of all f3’s methods. In your original example, it would’ve shown:
julia> methods(f3) # uh oh, where did the 1st method go?!
# 1 method for generic function "f3":
[1] f3(f2) in Main at REPL[3]:4
And in the fix:
julia> methods(f3)
# 2 methods for generic function "f3":
[1] f3(::typeof(f1)) in Main at REPL[3]:5
[2] f3(::typeof(f2)) in Main at REPL[3]:5