MSDN Magazine - March 2009 - (Page 33) Figure 3 The IL behind Let x=2 .assembly Library1 { .custom instance void [FSharp.Core]Microsoft.FSharp.Core. FSharpInterfaceDataVersionAttribute::.ctor(int32, int32, int32) = ( 01 00 01 00 00 00 09 00 00 00 06 00 00 00 00 00 ) // } .class public abstract auto ansi sealed beforefieldinit Module1 extends [mscorlib]System.Object { .custom instance void [FSharp.Core]Microsoft.FSharp.Core. CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft. FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) .method public static int32 get_x() cil managed { // Code size 6 (0x6) .maxstack 4 IL_0000: ldsfld int32 ' '.$Module1::x@3 IL_0005: ret } // end of method Module1::get_x .method private specialname rtspecialname static void .cctor() cil managed { // Code size 13 (0xd) .maxstack 3 IL_0000: ldc.i4.0 IL_0001: stsfld native int ' '.$Module1::_init IL_0006: ldsfld native int ' '.$Module1::_init IL_000b: pop IL_000c: ret } // end of method Module1::.cctor .property int32 x() { .custom instance void [FSharp.Core]Microsoft.FSharp.Core. CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft. FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) .get int32 Module1::get_x() } // end of property Module1::x } // end of class Module1 .class private abstract auto ansi sealed beforefieldinit ' '.$Module1 extends [mscorlib]System.Object { .field static assembly native int _init .custom instance void [mscorlib]System.Runtime.CompilerServices. CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) .field static assembly initonly int32 x@3 .method private specialname rtspecialname static void .cctor() cil managed { // Code size 8 (0x8) .maxstack 3 IL_0000: nop IL_0001: ldc.i4.2 IL_0002: stsfld int32 ' '.$Module1::x@3 IL_0007: ret } // end of method $Module1::.cctor } // end of class ' '.$Module1 whereas you might be tempted to think of x as a constant value that the compiler can inline, the compiler chooses to present it as a static property. This means, then, that accessing this binding, x, will require C# code something like the following: namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Console.WriteLine("F#'s x = {0}", Module1.x); } } } Figure 4 The IL for the Mapping Function .method public static class [FSharp.Core]Microsoft.FSharp.Collections. List'1 mymap (class [FSharp.Core]Microsoft.FSharp.Collections. List'1 l, class [FSharp.Core]Microsoft.FSharp.Core. FastFunc'2 f) cil managed { // Code size 11 (0xb) .maxstack 4 IL_0000: nop IL_0001: ldarg.1 IL_0002: ldarg.0 IL_0003: tail. IL_0005: call class [FSharp.Core]Microsoft.FSharp.Collections. List'1 [FSharp.Core]Microsoft.FSharp.Collections. ListModule::map (class [FSharp.Core]Microsoft. FSharp.Core.FastFunc'2 , class [FSharp.Core]Microsoft.FSharp.Collections.List'1 ) IL_000a: ret } // end of method Module1::mymap So far, so good. But x is a pretty simple binding, and as such, you would expect it to be a simple matter of accessing it. Something a bit more complicated could present some trickier problems, so let’s do something just a touch more complicated to make sure the mapping of F# to CLS still makes sense. For the F# code let add a b = a + b the compiler generates the additional IL into the “Module” class in the compiled F# DLL: .method public static int32 'add'(int32 a, int32 b) cil managed { // Code size 5 (0x5) .maxstack 4 IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 IL_0003: add IL_0004: ret } // end of method Module1::'add' look like, so there’s not a lot that needs to be explained here. Calling it is also trivial. But one of F#’s strengths is that it treats functions as first-class values, and this becomes more apparent (and more difficult) when you start building functions that take functions as arguments, such as the following equivalent of the built-in F# library map function, which takes as arguments a list, along with a function to apply to each element of the list, and returns a new list containing the results: let mymap (l : 'a list) (f : 'a -> 'b) = List.map f l This is almost precisely what the C# version of the function would msdnmagazine.com This is a particularly “functional” way of processing a list: rather than iterating through it item-by-item, a functional language takes March 2009 33 http://www.msdnmagazine.com
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.