有时F#即使标记为"inline"也不会内联函数? [英] Sometimes F# doesn't inline functions even if it is marked `inline`?
问题描述
let inline funA x =
printf "A"
x > 3
let inline funB myFun x =
printf "B"
myFun x
let foo () =
funB funA 7
IL表示foo
.method public static
bool foo () cil managed
{
// Method begins at RVA 0x2278
// Code size 31 (0x1f)
.maxstack 4
.locals init (
[0] class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [mscorlib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit>
)
IL_0000: nop
IL_0001: ldstr "B"
IL_0006: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5<class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [mscorlib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit>::.ctor(string)
IL_000b: stloc.0
IL_000c: call class [mscorlib]System.IO.TextWriter [mscorlib]System.Console::get_Out()
IL_0011: ldloc.0
IL_0012: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatToTextWriter<class [FSharp.Core]Microsoft.FSharp.Core.Unit>(class [mscorlib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<!!0, class [mscorlib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit>)
IL_0017: pop
IL_0018: ldc.i4.7
IL_0019: call bool Foo::myFun@21(int32) // Here!
IL_001e: ret
} // end of method Foo::foo
IL代表myFun@21
.method assembly static
bool myFun@21 (
int32 x
) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x224c
// Code size 29 (0x1d)
.maxstack 4
.locals init (
[0] class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [mscorlib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit>
)
IL_0000: ldstr "A"
IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5<class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [mscorlib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit>::.ctor(string)
IL_000a: stloc.0
IL_000b: call class [mscorlib]System.IO.TextWriter [mscorlib]System.Console::get_Out()
IL_0010: ldloc.0
IL_0011: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatToTextWriter<class [FSharp.Core]Microsoft.FSharp.Core.Unit>(class [mscorlib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<!!0, class [mscorlib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit>)
IL_0016: pop
IL_0017: nop
IL_0018: ldarg.0
IL_0019: ldc.i4.3
IL_001a: cgt
IL_001c: ret
} // end of method Foo::myFun@21
IL代表funA
.method public static
bool funA (
int32 x
) cil managed
{
// Method begins at RVA 0x2218
// Code size 22 (0x16)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "A"
IL_0006: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5<class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [mscorlib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit>::.ctor(string)
IL_000b: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormat<class [FSharp.Core]Microsoft.FSharp.Core.Unit>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<!!0, class [mscorlib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit>)
IL_0010: pop
IL_0011: ldarg.0
IL_0012: ldc.i4.3
IL_0013: cgt
IL_0015: ret
} // end of method Foo::funA
如您所见,myFun@21
与funA
几乎相同,我不知道为什么它存在.为何不内联函数?是因为我将一个函数作为参数传递给另一个函数吗?在这种情况下,我认为没有任何难解的闭包事情可以使其内联.
As you can see, myFun@21
is almost identical to funA
, I don't get why it exists. Also why the function is not inlined? Is it because I passed a function as an argument into another function? In this case I don't think there is any hard to resolve closure thing to make it impossible to inline.
当标记为inline
的函数无法内联时,是否有什么我可以了解的更多资源?
Are there any resources that I can learn more about when a function cannot be inlined though it is marked inline
?
推荐答案
我相信函数是内联的,只是不是您期望的那样. funA
仅在具有参数时才能内联.由于没有在使用时提供funA
的参数,因此编译器将其视为fun x -> funA x
并在其中内联funA
-这样就创建了一个lambda,就像您写了一样:
I believe that the function was inlined, just not in the way that you expected. funA
can only be inlined if it has an argument. Since you aren't providing an argument to funA
at the point of use, the compiler treats it as fun x -> funA x
and inlines funA
there - so a lambda is created and it's as if you wrote:
let foo() =
printf "B"
(fun x ->
printf "A"
x > 3) 7
这篇关于有时F#即使标记为"inline"也不会内联函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!