Continuations in Scala

The main idea of continuations in scala is the ability to interrupt a program, save its control state, and resume it at a later point in time. Continuations pop up on the web as a concept that could help with event-based programming. Continuations, and in particular delimited continuations, are a versatile programming tool. Most notably, we are interested in their ability to suspend and resume sequential code paths in a controlled way without the syntactic overhead and without being tied to VM threads.
So let’s try to understand it with a proper example. Imagine a read() function which returns a byte from the network:

def read: Byte 

This is typically the signature of a synchronous (blocking) function. After all, it has a return value and in normal programming languages, which means waiting for that value to be available. A program that reads two bytes in a row and prints them looks like this:

val byte1 = read
println(“byte1 = ” + byte1)
Val byte2 = read
println(“byte2 = ” + byte2)

The issue is that in a web browser or node.js or any other single-threaded, event-driven environment, this is not acceptable. we simply cannot block for a long time, otherwise, nothing else can happen in the system.
The issue here is that we must write in a funny style, even with Scala’s lightweight syntax for closures. Note also how each callback typically causes a new level of indentation. Some programmers manage to get used to this style, but it does not represent the control flow in a very natural way, and the issue grows with the size of the program.

import scala.util.continuations._
reset {
val byte1 = shift(read)
println(“byte1 = ” + byte1)
val byte2 = shift(read)
println(“byte2 = ” + byte2)}



We notice the reset and shift constructs. These terms don’t make any sense to a newcomer, but they have introduced a long time ago in an academic paper so are reused in Scala. Basically, reset delimits the continuation. With full continuations, the entire rest of the program would be under the control of the continuation, but here, whatever is before and after the reset block has nothing to do with continuations at all. (Also, reset can return a value, although here we don’t care about it.)

So in this example, follow the letters from A to Z

filter_none

edit
close

play_arrow

link
brightness_4
code

reset {
  // A
  shift { cf: (Int=>Int) =>
  
    // B
    val eleven = cf(10)
  
    // E
    println(eleven)
    val oneHundredOne = cf(100)
  
    // H
    println(oneHundredOne)
    oneHundredOne
  }
    
}

chevron_right


Output:

11
101

In above example when a continuation function cf is called:

  1. Execution skips over the rest of the shift block and begins again at the end of it. the parameter passed to cf is what the shift block “evaluates” to as execution continues. this can be different for every call to cf.
  2. Execution continues until the end of the reset block (or until a call to reset if there is no block). the result of the reset block (or the parameter to reset() if there is no block) is what cf returns.
  3. Execution continues after cf until the end of the shift block.
  4. Execution skips until the end of the reset block (or a call to reset?)

let’s see one more example:

filter_none

edit
close

play_arrow

link
brightness_4
code

reset {
    println("A")
    shift { k1: (Unit=>Unit) =>
        println("B")
        k1()
        println("C")
    }
    println("D")
    shift { k2: (Unit=>Unit) =>
        println("E")
        k2()
        println("F")
    }
    println("G")
}

chevron_right


Output:

A
B
D
E
G
F
C



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.


Article Tags :

1


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.