Concepts of Programming Languages

(Sean Pound) #1

432 Chapter 9 Subprograms


The makeAdder function is called twice, once with a parameter of 10 and once
with 5. Each of these calls returns a different version of the closure because
they are bound to different values of x. The first call to makeAdder creates a
function that adds 10 to its parameter; the second creates a function that adds
5 to its parameter. The two versions of the function are bound to different
activations of makeAdder. Obviously, the lifetime of the version of x created
when makeAdder is called must extend over the lifetime of the program.
This same closure function can be written in C# using a nested anonymous
delegate. The type of the nesting method is specified to be a function that takes
an int as a parameter and returns an anonymous delegate. The return type
is specified with the special notation for such delegates, Func<int, int>.
The first type in the angle brackets is the parameter type. Such a delegate can
encapsulate methods that have only one parameter. The second type is the
return type of the method encapsulated by the delegate.

static Func<int, int> makeAdder(int x) {
return delegate(int y) { return x + y;};
}

Func<int, int> Add10 = makeAdder(10);
Func<int, int> Add5 = makeAdder(5);
Console.WriteLine("Add 10 to 20: {0}", Add10(20));
Console.WriteLine("Add 5 to 20: {0}", Add5(20));

The output of this code is exactly the same as for the previous JavaScript clo-
sure example.
The anonymous delegate could have been written as a lambda expression.
The following is a replacement for the body of the makeAdder method, using
a lambda expression instead of the delegate:

return y => x + y

Ruby’s blocks are implemented so that they can reference variables visible
in the position in which they were defined, even if they are called at a place in
which those variables would have disappeared. This makes such blocks closures.

9.13 Coroutines


A coroutine is a special kind of subprogram. Rather than the master-slave
relationship between a caller and a called subprogram that exists with conven-
tional subprograms, caller and called coroutines are more equitable. In fact, the
coroutine control mechanism is often called the symmetric unit control model.
Coroutines can have multiple entry points, which are controlled by the
coroutines themselves. They also have the means to maintain their status
between activations. This means that coroutines must be history sensitive and
Free download pdf