Datasheet

20
x
CHAPTER 1 PRIMER
In the lambda calculus, this operation can be thought of as asking a function to take an int and
another function, where that second function takes an
int and returns an int back. So, in C# 2.0,
converting this to look like what the lambda calculus implies, starting with the
Add method con-
verted to a delegate operation:
private delegate int Operation(int l, int r);
static void MoreMathExamples()
{
int result = Add(2, 3);
Operation add = delegate(int l, int r) { return l + r; };
int result2 = add(2, 3);
}
then means the delegate can be broken up into two different delegates — the fi rst handing back a
delegate that in turn knows how to do the actual operation:
delegate InnerOp DelegateOp(int r);
delegate int InnerOp(int l);
static void MoreMathExamples()
{
int result = Add(2, 3);
Operation add1 = delegate(int l, int r) { return l + r; };
int result2 = add1(2, 3);
DelegateOp add2 = delegate(int l)
{
return delegate(int r)
{
return l + r;
};
};
int result3 = add2(2)(3);
}
This process is known as currying, named after Haskell Curry, another mathematician who was
famous (among mathematicians, at least). Because this sequence of steps should be applicable for
more than just integers, a quick application of generics makes it available for any type:
Func<int,Func<int, int>> add4 =
delegate(int l)
{
return delegate(int r)
{
return l + r;
};
};
int result4 = add4(2)(3);
Then, on top of all this, the whole process can be further genericized by creating a standard-purpose
method for doing it:
delegate U Op<T1, T2, U>(T1 arg1, T2 arg2);
delegate U Op<T1, U>(T1 arg1);
c01.indd 20c01.indd 20 10/1/2010 3:20:38 PM10/1/2010 3:20:38 PM