Wednesday, May 30, 2018

Continuations Reset and Shift


I have been researching continuations in Scala - using some links from the ThoughtWorks DSL page.

https://static.javadoc.io/com.thoughtworks.dsl/dsl_2.12/1.0.0-RC10/com/thoughtworks/dsl/index.html


I would suggest anyone interested in some of the more powerful features of Scala to have a tour of the links on that page

First one that caught my eyes was this:

https://www.schoolofhaskell.com/school/to-infinity-and-beyond/pick-of-the-week/the-mother-of-all-monads

import Control.Monad.Cont

ex4 = do
    a <- -="" 1="" b="" cont="" fred="" return=""> fred 10 ++ fred 20)
    return $ a+b

test4 = runCont ex4 show

main = print test4
We've used fred twice. We've made the code around our "hole" run twice, each time executing with a different starting value. Continuations allow mere subexpressions to take complete control of the expressions within which they lie.

This page led me to another page clearly explains continuations in Scala

http://blog.bruchez.name/2011/09/continuations-in-scala.html


Enter Scala continuations:
import scala.util.continuations._
reset {
  val byte1 = shift(read)
  println("byte1 = " + byte1)
  val byte2 = shift(read)
  println("byte2 = " + byte2)
}
And voilĂ : you can write the program again in imperative style without callbacks and closures.
You notice the reset and shift constructs. These terms don’t make any sense to a newcomer, but they were 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 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.)
shift is the construct that does the real magic. Mainly, it smartly hacks around to pass the continuation, that is a closure containing whatever-code-follow-shift-until-the-end-of-the-reset-block, to its body. If you run that closure, you actually run that code after the shift. If you store that closure somewhere, you gain the ability to decide when to run that code at a later point. This is the general idea of continuations: interrupt, then resume a program. Here it’s all done with functions and closures behind the scene.

No comments: