Using @eval with zipped pair of Symbols

f1(x) = x+1
f2(x) = x+2
  
for (t, op) in zip((:Int, :Float64),(:f1, :f2))
  print(t, " ", op, "\n")
  @eval begin
    f3($op) = begin
      println($t)
      println($op)
      x -> $t($op(x) + 3) 
    end
  end
end

f3(f1)(2) # return 6.0
f3(f2)(2) # return 7.0

why doesn’t f3(f1)(2) return 6 (as Int) as the evaluated line should be x -> Int(f1(x) + 3)?

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

Aha! So in my version the second loop just overwrites the first one, thanks!

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