The way I understand it is... the hierarchy relationships displayed in your code are translated into a similarly structured series of classes and methods, as necessary.
In fixed systems, such as the .NET framework, the Lambda expression itself would be lifted into its own method to account for giving the method a place in the CLI's VTable for the class that defines the methods that uses the lambda expression. This also makes logical sense as opposed to creating a completely new portion of application code every time you call the method.
Things get trickier when you deal in closures. If a condition occurs where a local from the lambda's declaring method is referenced inside the lambda (the ctr example you're giving), the compiler needs to perform extra work to handle the reference, so that it's still valid, but doesn't require an extra parameter to be added to the lambda's signature (which would break using the lambda on cases where a method call requires a pointer to a method of a given signature).
The extra work involves creating a completely new class (within the scope of the method that used the lambda, so private members of the class can still be referenced inside the lambda). The class would contain the variable the lambda expression references. The original method that defined the local would now refer to the value defined within the newly generated class.
Here's an example (written in C#, since it uses lambdas):
public void TestMethod(){ var i = 0; FuncV inc = () => { i++; }; //I believe the equivalent everyone else's been using is: //var inc = func(){i++;} for (int k = 0; k < 10; k++){ inc(); Console.WriteLine(i); }}
Here's the example of how the compiler/interpreter would restructure the code:
private class LambdaGenerated_TestMethod{ internal int tm_i; internal void LambdaGeneratedMethod0001() { this.tm_i++; }}public void TestMethod(){ var incSrc = new LambdaGenerated_TestMethod(); incSrc.tm_i = 0; //var i = 0; for (int k = 0; k < 10; k++) { incSrc.LambdaGeneratedMethod0001(); Console.WriteLine(incSrc.tm_i); }}
Depending on your language's implementation you can ignore the public/private/internal scoping.
There's also one important thing to note about lambda expressions. In the above example you noticed that it replaced the variable 'i' with a reference to the class that defined the lambda and its internal storage for i. If you were to make an array of func() instances all from the same lambda, all would contain a reference to the same exact 'i' and all would be the same instance, depending on the scope of where 'i' was originally sourced. If 'i' was from the scope of the method, there'd be one instance of LambdaGenerated_TestMethod; however, if the 'i' was sourced from a variable declared
inside a loop, it would contain multiple instances, because the value was sourced from a sub-scope, and the instances of LambdaGenerated_TestMethod would go out of scope similarly as the values it references.
Edit:
I forgot to mention that the example I gave is slightly different from how C# actually generates its solution for lambdas/closures. The only real difference is C# actively refers to the original delegate type (FuncV) to invoke the method instead of calling it directly, I went for the example shown to emphasize from the examples here that there's no real type implied; thus, why the example calls the class member function directly, instead of being piped through a function pointer (delegate).
[Edited by - AlexanderMorou on July 26, 2008 11:11:01 PM]