Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create local functions in F#

For example, I have 2 additive functions:

module Add

let add2 a =
    let innerFn a = a + 2
    innerFn a
let add2' a =
    let innerFn' () = a + 2
    innerFn' ()

let res1 = add2 0
let res2 = add2' 1

From what I known, both innerFns will be compiled to FSharpFunc<int,int> and FSharpFunc<unit,int> respectively, and will be initialized everytime the add2 or add2' is called.

How can I rewrite the code to transform them to static local functions of the static class (thus no FSharpFunc initialization), like in C# 7?

like image 461
MiP Avatar asked Jan 30 '23 00:01

MiP


1 Answers

You probably don't have to worry about this. In a Debug build, every local function becomes a delegate. In a Release build, the functions are either inlined or do become static methods in the static class.

By building and decompiling the question's code in a Debug build, you get :

public static int add2(int a)
{
    return 5 + (new Program.innerFn@5()).Invoke(a);
}

public static int add2'(int a)
{
    return (new Program.innerFn'@8(a)).Invoke(null);
}

Which does show a delegate initialization each time.

In Release though, this becomes :

public static int add2(int a)
{
    return a + 2;
}

public static int add2'(int a)
{
    return a + 2;
}

The functions were inlined and no delegate was generated.

To avoid indlining, I made add2 a bit more complex :

let add2 a =
    let innerFn a = if a < 3 then a+1 else a + 2
    5 + innerFn a
let add2' a =
    let innerFn' () = a + 2
    innerFn' () 

In this case, the Release build generated a static method in the class :

public static int add2(int a)
{
    return 5 + Program.innerFn@5(a);
}

public static int add2'(int a)
{
    return a + 2;
}

internal static int innerFn@5(int a)
{
    if (a < 3)
    {
        return a + 1;
    }
    return a + 2;
}
like image 184
Panagiotis Kanavos Avatar answered Feb 04 '23 18:02

Panagiotis Kanavos