I have a question regarding continuations in C#. I have an example here from the book, Real World Functional Programming by Tomas Petricek and Jon Skeet.
void StringLengthCont(string s, Action<int> cont) {
cont(s.Length);
}
void AddLengthsCont() {
StringLengthCont("One", x1 =>
StringLengthCont("Two", x2 =>
Console.WriteLine(x1 + x2)
))
}
Now this is very confusing for me. In this case, we have a method, StringLengthCont
which expects a string, s
and an Action<int> cont
and it then invokes that Action<int>
with the length of s
as an argument.
So far I understand. But the inner lambda of the last call to StringLengthCont
doesn't that have signature of Action<int,int>
? It seems to me it takes two integers, adds them together and returns a void.
But the inner lambda of the last call to StringLengthCont doesn't that have signature of Action ?
No. What happens is the following:
You call StringLengthCont
the first time, which takes an Action<int>
. The actual action being passed (as a Lambda Expression) calls StringLengthCont
again. The second time, it passes "Two" as the string parameter, and creates a parameter named x2
which is being passed to StringLengthCont
(the second) as a parameter. Because both x1
and x2
are still in scope (this happens with captured variables and the way the compiler handles lambda expressions), we pass them to Console.WriteLine
in order to print the addition of those two ints.
Maybe looking at this way will make it clearer:
StringLengthCont("One", new Action<int>(x1 =>
StringLengthCont("Two",
new Action<int>((x2) =>
Console.WriteLine(x1 + x2)))));
Or perhaps this way:
void AddLengthsCont()
{
StringLengthCont("One", x1 => CallStringLengthAgain(x1));
}
private void CallStringLengthAgain(int x1)
{
StringLengthCont("Two", x2 => Console.WriteLine(x1 + x2));
}