Search code examples
c#.netlambdaclosurescontinuations

Continuations in C#


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.


Solution

  • 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));
    }