inline - How does nesting f# functions differ from not nesting them when nesting is optional? -


i understand benefit of nesting functions when want return closure. when function never used outside of function defined in, there cost keeping nested?

consider:

let private validate number =      number > 100  let validateandprint (i : int) =      printfn "%i greater 100: %s" ((validate i).tostring()) 

versus:

let validateandprint (i : int) =      let validate number =          number > 100     printfn "%i greater 100: %s" ((validate i).tostring()) 

the concern here when have few of these inner functions , need call 1 of them based on execution path (it's not prohibitive keep these functions private or nested , test permutations).

validateandprint rewritten more tdd-friendly take in validate function:

let validateandprint validate = ... 

..but if validation's signature contains internal or private type there consideration of making public , parameter list blowing up.

any crucial differences?

in release mode, il identical , both versions of validate inlined in particular example.

you cannot rely on inlining always, e.g. if function "big" compiler choose not inline (this true methods, not 100% sure true f# nested functions. not possible mark them inline , force inlining, - need consult f# specs if such functions behave methods or inlined in release). in nested case in debug mode, there additional fsharpfunc allocation , callvirt. without nesting static call without allocations, cheapest of possible implementations.

so in general, if nesting optional safer avoid it, because if function not inlined called static method. however, matters when call code several millions times per second.

not nested, static call on il_0019:

.method public static      void validateandprint (         int32     ) cil managed  {     // method begins @ rva 0x2104     // code size 51 (0x33)     .maxstack 5     .locals init (         [0] class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<int32, class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<string, class [fsharp.core]microsoft.fsharp.core.unit>>,         [1] bool     )      il_0000: ldstr "%i greater 100: %s"     il_0005: newobj instance void class [fsharp.core]microsoft.fsharp.core.printfformat`5<class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<int32, class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<string, 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 [mscorlib]system.tuple`2<int32, string>>::.ctor(string)     il_000a: call !!0 [fsharp.core]microsoft.fsharp.core.extratopleveloperators::printformatline<class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<int32, class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<string, 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_000f: stloc.0     il_0010: nop     il_0011: ldloc.0     il_0012: newobj instance void fsso.test/validateandprint@8::.ctor(class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<int32, class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<string, class [fsharp.core]microsoft.fsharp.core.unit>>)     il_0017: ldarg.0     il_0018: ldarg.0     il_0019: call bool fsso.test::validate(int32)     il_001e: stloc.1     il_001f: ldloca.s 1     il_0021: constrained. [mscorlib]system.boolean     il_0027: callvirt instance string [mscorlib]system.object::tostring()     il_002c: call !!0 class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<int32, string>::invokefast<class [fsharp.core]microsoft.fsharp.core.unit>(class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<!0, class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<!1, !!0>>, !0, !1)     il_0031: pop     il_0032: ret } // end of method test::validateandprint 

nested, allocation on il_0018 , callvirt on il_0020:

.method public static      void validateandprint (         int32     ) cil managed  {     // method begins @ rva 0x2050     // code size 58 (0x3a)     .maxstack 6     .locals init (         [0] class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<int32, bool> validate,         [1] class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<int32, class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<string, class [fsharp.core]microsoft.fsharp.core.unit>>,         [2] bool     )      il_0000: newobj instance void fsso.test2/validate@13::.ctor()     il_0005: stloc.0     il_0006: ldstr "%i greater 100: %s"     il_000b: newobj instance void class [fsharp.core]microsoft.fsharp.core.printfformat`5<class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<int32, class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<string, 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 [mscorlib]system.tuple`2<int32, string>>::.ctor(string)     il_0010: call !!0 [fsharp.core]microsoft.fsharp.core.extratopleveloperators::printformatline<class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<int32, class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<string, 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_0015: stloc.1     il_0016: nop     il_0017: ldloc.1     il_0018: newobj instance void fsso.test2/'validateandprint@14-2'::.ctor(class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<int32, class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<string, class [fsharp.core]microsoft.fsharp.core.unit>>)     il_001d: ldarg.0     il_001e: ldloc.0     il_001f: ldarg.0     il_0020: callvirt instance !1 class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<int32, bool>::invoke(!0)     il_0025: stloc.2     il_0026: ldloca.s 2     il_0028: constrained. [mscorlib]system.boolean     il_002e: callvirt instance string [mscorlib]system.object::tostring()     il_0033: call !!0 class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<int32, string>::invokefast<class [fsharp.core]microsoft.fsharp.core.unit>(class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<!0, class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<!1, !!0>>, !0, !1)     il_0038: pop     il_0039: ret } // end of method test2::validateandprint 

release mode, inlined comparison on il_0020:

.method public static      void validateandprint (         int32     ) cil managed  {     // method begins @ rva 0x2050     // code size 57 (0x39)     .maxstack 6     .locals init (         [0] class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<int32, class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<string, class [fsharp.core]microsoft.fsharp.core.unit>>,         [1] class [fsharp.core]microsoft.fsharp.core.printfformat`4<class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<int32, class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<string, 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>,         [2] bool     )      il_0000: ldstr "%i greater 100: %s"     il_0005: newobj instance void class [fsharp.core]microsoft.fsharp.core.printfformat`5<class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<int32, class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<string, 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 [mscorlib]system.tuple`2<int32, string>>::.ctor(string)     il_000a: stloc.1     il_000b: call class [mscorlib]system.io.textwriter [mscorlib]system.console::get_out()     il_0010: ldloc.1     il_0011: call !!0 [fsharp.core]microsoft.fsharp.core.printfmodule::printformatlinetotextwriter<class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<int32, class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<string, 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: stloc.0     il_0017: nop     il_0018: ldloc.0     il_0019: newobj instance void fsso.test2/'validateandprint@14-2'::.ctor(class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<int32, class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<string, class [fsharp.core]microsoft.fsharp.core.unit>>)     il_001e: ldarg.0     il_001f: ldarg.0     il_0020: ldc.i4.s 100     il_0022: cgt     il_0024: stloc.2     il_0025: ldloca.s 2     il_0027: constrained. [mscorlib]system.boolean     il_002d: callvirt instance string [mscorlib]system.object::tostring()     il_0032: call !!0 class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<int32, string>::invokefast<class [fsharp.core]microsoft.fsharp.core.unit>(class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<!0, class [fsharp.core]microsoft.fsharp.core.fsharpfunc`2<!1, !!0>>, !0, !1)     il_0037: pop     il_0038: ret } // end of method test2::validateandprint 

Comments

Popular posts from this blog

php - Wordpress website dashboard page or post editor content is not showing but front end data is showing properly -

How to get the ip address of VM and use it to configure SSH connection dynamically in Ansible -

javascript - Get parameter of GET request -