有时F#即使标记为"inline"也不会内联函数? [英] Sometimes F# doesn't inline functions even if it is marked `inline`?

查看:85
本文介绍了有时F#即使标记为"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@21funA几乎相同,我不知道为什么它存在.为何不内联函数?是因为我将一个函数作为参数传递给另一个函数吗?在这种情况下,我认为没有任何难解的闭包事情可以使其内联.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆