Function 使闭包类型稳定取决于捕获的变量

Function 使闭包类型稳定取决于捕获的变量,function,julia,type-stability,Function,Julia,Type Stability,对于函数 function function_maker(N) if N == 1 x = 1.0 else x = 1 end f(y) = x+y end 我希望它的输出不是类型稳定的,但我希望它生成一个类型稳定的f,即使用x的类型,该类型由N的值确定,以生成依赖于N的函数。基本上,我希望由此产生的功能能够被执行,但是函数\u maker本身不需要被执行,因为它只在全局范围内或在功能屏障之上使用 f = function_ma

对于函数

function function_maker(N)
    if N == 1
        x = 1.0
    else
        x = 1
    end
    f(y) = x+y
end
我希望它的输出不是类型稳定的,但我希望它生成一个类型稳定的
f
,即使用
x
的类型,该类型由
N
的值确定,以生成依赖于
N
的函数。基本上,我希望由此产生的功能能够被执行,但是
函数\u 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
分开。否则编译器似乎会感到困惑。

这很有趣!更改变量(x和xx)没有帮助:
function\u maker3(N)N==1&&begin x=1。;返回y->x+y结束| |开始xx=1;返回y->xx+y结束
。但是只将第一个(!)
开始
替换为
工作。只替换第二个不起作用。回答真的很酷!这绝对是一个我必须记住的把戏。@Liso你所描述的很有趣。为了让双变量名函数返回类型stable
f
,我需要在条件路径之前添加
local x::Float64,xx::Int64
,这样编译器就不会对未调用的条件路径中的局部变量的类型产生不确定性。至于第一个和第二个之间的
let
不对称,您是否测试了
f
返回的
函数生成器(1)
函数生成器(2)
的稳定性?也许
let
分支是稳定的,而另一个分支不是。@DanGetz你说得对!对不起,我太快了…:/我在错误的位置更改了参数(分别是
函数\u生成器(1)
函数\u生成器(1)
-这是无用的)。因此,将
begin
更改为let是可以预期的。我不确定我在本地做了什么错误,但这对我来说不起作用:
function\u maker3(N)local x::Float64,xx::Int64;N==1&&begin x=1。;返回y->x+y结束| |开始xx=1;返回y->xx+y结束;f2=函数3(1)@code\u warntype f2(1)
@Liso它对我有效,因为它提供了一个稳定的类型
f2(1)
。使用Julia版本0.6.2-pre.3