Search code examples
scalaresetcontinuations

Example of nested resets in Scala


This is a question about Scala continuations. Can resets be nested? If they can: what are nested resets useful for ? Is there any example of nested resets?


Solution

  • Yes, resets can be nested, and, yes, it can be useful. As an example, I recently prototyped an API for the scalagwt project that would allow GWT developers to write asynchronous RPCs (remote procedure calls) in a direct style (as opposed to the callback-passing style that is used in GWT for Java). For example:

    field1 = "starting up..."                   // 1 
    field2 = "starting up..."                   // 2 
    async {                                     // (reset)
       val x = service.someAsyncMethod()        // 3 (shift)
       field1 = x                               // 5 
       async {                                  // (reset)
          val y = service.anotherAsyncMethod()  // 6 (shift)
          field2 = y                            // 8 
       } 
       field2 = "waiting..."                    // 7 
    } 
    field1 = "waiting..."                       // 4 
    

    The comments indicate the order of execution. Here, the async method performs a reset, and each service call performs a shift (you can see the implementation on my github fork, specifically Async.scala).

    Note how the nested async changes the control flow. Without it, the line field2 = "waiting" would not be executed until after successful completion of the second RPC.

    When an RPC is made, the implementation captures the continuation up to the inner-most async boundary, and suspends it for execution upon successful completion of the RPC. Thus, the nested async block allows control to flow immediately to the line after it as soon as the second RPC is made. Without that nested block, on the other hand, the continuation would extend all the way to the end of the outer async block, in which case all the code within the outer async would block on each and every RPC.