What are Scala continuations and why use them?
My blog does explain what reset
and shift
do, so you may want to read that again.
Another good source, which I also point in my blog, is the Wikipedia entry on continuation passing style. That one is, by far, the most clear on the subject, though it does not use Scala syntax, and the continuation is explicitly passed.
The paper on delimited continuations, which I link to in my blog but seems to have become broken, gives many examples of usage.
But I think the best example of the concept of delimited continuations is Scala Swarm. In it, the library stops the execution of your code at one point, and the remaining computation becomes the continuation. The library then does something -- in this case, transferring the computation to another host, and returns the result (the value of the variable which was accessed) to the computation that was stopped.
Now, you don't understand even the simple example on the Scala page, so do read my blog. In it I'm only concerned with explaining these basics, of why the result is 8
.
I found the existing explanations to be less effective at explaining the concept than I would hope. I hope this one is clear (and correct.) I have not used continuations yet.
When a continuation function cf
is called:
- Execution skips over the rest of the
shift
block and begins again at the end of it- the parameter passed to
cf
is what theshift
block "evaluates" to as execution continues. this can be different for every call tocf
- the parameter passed to
- Execution continues until the end of the
reset
block (or until a call toreset
if there is no block)- the result of the
reset
block (or the parameter toreset
() if there is no block) is whatcf
returns
- the result of the
- Execution continues after
cf
until the end of theshift
block - Execution skips until the end of the
reset
block (or a call to reset?)
So in this example, follow the letters from A to Z
reset {
// A
shift { cf: (Int=>Int) =>
// B
val eleven = cf(10)
// E
println(eleven)
val oneHundredOne = cf(100)
// H
println(oneHundredOne)
oneHundredOne
}
// C execution continues here with the 10 as the context
// F execution continues here with 100
+ 1
// D 10.+(1) has been executed - 11 is returned from cf which gets assigned to eleven
// G 100.+(1) has been executed and 101 is returned and assigned to oneHundredOne
}
// I
This prints:
11
101