Jul 8, 2011

f# essential - part 12 - function is not method, is not delegate, what is it anyway

As previous post discussed, f# function is not a method, because it support closure, it curry and so on, and .net method does not support these. It looks very much like a delegate (aka lambda, anonymous method) in .net. For example, the following looks like it is a delegate.

open System
open System.Linq

let l = [ 1; 2; 3 ]
let conditionFunction i = i > 1
let c = l.Where(conditionFunction).Count()

But it is not, the case compiler is actually something similar like the following.

let l = [ 1; 2; 3 ]
let conditionFunction i = i > 1
let conditionDelegate = new System.Func<_, _>(conditionFunction)
let c1 = l.Where(conditionDelegate).Count()

So let's use reflector again.

[CompilationMapping(SourceConstructFlags.Module)]
public static class Program
{
    // Methods
    public static bool conditionFunction(int i)
    {
        return (i > 1);
    }

    // Properties
    [CompilationMapping(SourceConstructFlags.Value)]
    public static int c
    {
        get
        {
            return $Program.c@36;
        }
    }

    [CompilationMapping(SourceConstructFlags.Value)]
    public static Func<int, bool> conditionDelegate
    {
        get
        {
            return $Program.conditionDelegate@34;
        }
    }

    [CompilationMapping(SourceConstructFlags.Value)]
    public static FSharpList<int> l
    {
        get
        {
            return $Program.l@32;
        }
    }

    // Nested Types
    [Serializable, CompilationMapping(SourceConstructFlags.Closure)]
    internal sealed class conditionDelegate@34
    {
        // Methods
        internal bool Invoke(int arg)
        {
            return Program.conditionFunction(arg);
        }
    }
 
 public static void main@()
    {
        FSharpList<int> l = l@32 = FSharpList<int>.Cons(1, FSharpList<int>.Cons(2, FSharpList<int>.Cons(3, FSharpList<int>.get_Empty())));
        Func<int, bool> conditionDelegate = conditionDelegate@34 = new Func<int, bool>(new Program.conditionDelegate@34().Invoke);
        int c = c@36 = Program.l.Where<int>(Program.conditionDelegate).Count<int>();
        Program.conditionFunction(1);
    }
}