Skip to main content

Antonio Cisternino's Home Page

Go Search
Home
  
Antonio Cisternino's Home Page > My Blog > Closures in CLR 2.0  

My Blog: Closures in CLR 2.0

Title

Closures in CLR 2.0 

Body

I found some time to play with CLR 2.0, the upcoming version of .NET and I was glad to see that in the end delegates have been extended with a feature that fixed a design flaw of version 1.0.
When I first met Jim Miller he said to me that they designed delegates to support closures of functional programming languages within CLR, and only in the end turned out that the design wasn't enough to support closures.
At that time it tooks me to work out the problem, probably because I wasn't really aware of issues of implementing closures in programming languages.
Now I think I have a better understanding of the problem, and I try to put into words. Consider the following example (legal in C# 2.0):
 
delegate void F(int i);
...
F bar() {
  int j = 0;
  F f = delegate (int p) { Console.WriteLine("Call {0} with par {1}", j++, f); }
  f(2); // Print "Call 0 with par 2"
  f(3); // Print "Call 1 with par 3"
  Console.WriteLine("j = {0}", j); // Print "j = 2"
  j++;
  Console.WriteLine("j = {0}", j); // Print "j = 3"
  f(1); // Print "Call 3 with par 1"
 
  return f;
}
 
void baz() {
  F g = bar();
  g(5); // Print "Call 4 with par 5"
}
 
We define an anonymous delegate f within bar, whose definition is inside the method. It is plain that the definition of f refers to the local variable j into the body. Each time the delegate is invoked its body modifies j as shown in the example above.
At the end of bar the delegate f is returned to the caller (in our case baz) still holding the reference to variable j (though nobody else now can reference it because it is out of scope). When we invoke g we get a print with the updated value of j.
Thus closing a value is a mean to extend the lifetime of a variable and allow other code to change variables closed in functions.
Closures are not created by Microsoft, it is a long time that are used by functional programming languages.
With closures it is possible to implement objects: a closure can be used to call methods on closed values (what if j where an object rather than an int?). In a OO language like C# are useful when a simple state should be closed into a function without bothering introducing a new class (as a matter of fact this is done by the compiler for you).
 
But let's go back to our main point: delelgates and closures within CLR. The essence of a closure is that you capture a variable from its scope by referring it from a method body of an anonymous delegate (as a matter of fact here delegate keyword plays the role of lambda). In functional programming languages closures are compiled to standard functions with the first argument bound to the environment: the set of values captured by the closure. In our example the environment is made by the single variable j (note that method bar is such that it refers j in the environment rather than on the stack).
 
Now a delegate, as it was defined in CLR 1.x, is a kind of closure: the object this is closed on the method. The this pointer is in fact the argument 0 of a method call and plays the same role of the environment in a closure. With a delegate it is possible to pack into a single object (a pair) the this reference and a reference to the method.
 
The problem with implementation of delegates in CLR 1.x was the additional constraint that the pair (this, meth) of a delegate imposes that meth is an instance method and this is an object where the method is declared. Besides, in closures the function and the environment have no relation apart from the fact that the environment is passed as first argument of it.
 
I hope I made the point clear, though it took me a while to work it out. And what's new in CLR 2.0? Consider the following example:
 
delegate void F(int i);
...
static void Meth(string s, int j) {
  Console.WriteLine("{0} {1}", s, j);
}
...
F f = Delegate.CreateDelegate(typeof(F), "Hello", typeof(this).GetMethod("Meth"));
f(2); // Print "Hello 2"
 
In this example we see that now we can build a delegate out of a static method and a value (that is considered to be its first argument). The delegate f holds inside the "Hello" string and when it is invoked the first argument of method Meth is bound to this value, the remaining arguments are taken from the arguments of the delegate.
 
With this small extension now CLR removes the constraint that the reference to an object into a delegate is intended as the this pointer of the specified instance method. This is good because now there is some hope that functional programming languages get better support for compilation; moreover closures are really handy when small state should be bound to a method: it helps us to avoid introducing a class.
 
An example? Think for example of a calculator: a single delegate may handle all the keys and represent the state (the accumulator and the display) as closed variables instead of having to define a class.
 
Stay tuned! More will come on this argument soon!

Expires

 

Category

Programming 
Attachments
Created at 4/19/2004 22:25  by Antonio Cisternino 
Last modified at 4/20/2004 1:16  by Antonio Cisternino