问题
let inline funA x =
printf "A"
x > 3
let inline funB myFun x =
printf "B"
myFun x
let foo () =
funB funA 7
IL for 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 for 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 for 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
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.
Are there any resources that I can learn more about when a function cannot be inlined though it is marked inline
?
回答1:
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
来源:https://stackoverflow.com/questions/17912509/sometimes-f-doesnt-inline-functions-even-if-it-is-marked-inline