使闭包类型稳定依赖于捕获的变量

Making closures type-stable dependent on the captured variable

对于函数

function function_maker(N)
    if N == 1
        x = 1.0
    else
        x = 1
    end
    f(y) = x+y
end

我希望它的输出不是类型稳定的,但我希望它生成类型稳定的 f,即使用由值确定的 x 类型N 生成依赖于 N 的函数。基本上,我希望由此产生的函数是高性能的,但是 function_maker 本身不需要是高性能的,因为它只在全局范围内或函数屏障之上使用。

f = function_maker(1)
@code_warntype f(1)

Variables:
  #self#::#f#9
  y::Int64

Body:
  begin 
      return ((Core.getfield)((Core.getfield)(#self#::#f#9, :x)::ANY, :contents)::ANY + y::Int64)::ANY
  end::ANY

默认情况下不会发生这种情况。我尝试了 f(y) = x::typeof(x)+y 但这也没有用。有没有简单的方法可以做到这一点?

有:

julia> function function_maker2(N)
           if N == 1
               let x = 1.0
                   return f(y) = x + y
               end
           else
               let x = 1
                   return f(y) = x + y
               end
           end
       end
function_maker2 (generic function with 1 method)

julia> f2 = function_maker2(1)
(::f) (generic function with 1 method)

julia> @code_warntype f2(1)
Variables:
  #self#::#f#5{Float64}
  y::Int64

Body:
  begin 
      return (Base.add_float)((Core.getfield)(#self#::#f#5{Float64}, :x)::Float64, (Base.sitofp)(Float64, y::Int64)::Float64)::Float64
  end::Float64

此版本在 let 块内的每个分支中分隔 x。否则编译器似乎会混淆。