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你所描述的很有趣。为了让双变量名函数返回类型stablef
,我需要在条件路径之前添加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