30 Jun 2010

F# Currying


Let’s look at how currying works behind the scenes. It is not very surprising that this code

let adder x y = x + y
let partial x = adder 2 + y

is compiled to

.method public static int32 adder(int32 x, int32 y) cil managed 
{
  .custom instance void Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[])
    = (01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) // 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 Program::adder

.method public static int32 partial(int32 x) cil managed
{
  // Code size 9 (0x9)
  .maxstack 4
    IL_0000: nop
    IL_0001: ldc.i4.2
    IL_0002: ldarg.0
    IL_0003: call int32 Program::adder(int32,int32)
    IL_0008: ret
} // end of method Program::partial

which comes down to the following common C# code

public class Test { public static int adder(int x, int y) { return (x + y); }
public static int partial(int x) { return (adder(x, 2)); } }

and it does generate a similar IL code:

.method public hidebysig static int32 adder(int32 x,int32 y) cil managed
{
  // Code size 9 (0x9)
  .maxstack 2
  .locals init ([0] int32 CS$1$0000)
  IL_0000: nop
  IL_0001: ldarg.0
  IL_0002: ldarg.1
  IL_0003: add
  IL_0004: stloc.0
  IL_0005: br.s IL_0007
  IL_0007: ldloc.0
  IL_0008: ret
} // end of method Test::adder .method

public hidebysig static int32 partial(int32 x) cil managed
{
  // Code size 13 (0xd)
  .maxstack 2
  .locals init ([0] int32 CS$1$0000)
  IL_0000: nop
  IL_0001: ldarg.0
  IL_0002: ldc.i4.2
  IL_0003: call int32 CSharpTest.Test::adder(int32,int32)
  IL_0008: stloc.0
  IL_0009: br.s IL_000b
  IL_000b: ldloc.0
  IL_000c: ret
} // end of method Test::partial

blog comments powered by Disqus