Rich Dougherty rd.nz

Goto in Scala

Ever wished you could use goto in your Scala programs? :-) You'll be glad to know that a new compiler plugin, currently in development, makes it possible.

import Goto._

reset {
  var sum = 0
  var i = 0
  val beforeLoop = label // Create label for goto
  if (i < 10000) {
    println(i)
    sum += i
    i += 1
    goto(beforeLoop) // Jump to label
  }
  println(sum)
}

The new plugin brings delimited continuations to Scala. With continuation support, it becomes possible for end users to extend the language in new and interesting ways. For example, it is possible to write new control flow operations. Here's some code that implements the famous goto operation, which was for some reason omitted from the Scala language.

object Goto {

  case class Label(k: Label => Unit)

  private case class GotoThunk(label: Label) extends Throwable

  def label: Label @suspendable =
    shift((k: Label => Unit) => executeFrom(Label(k)))

  def goto(l: Label): Nothing =
    throw new GotoThunk(l)

  private def executeFrom(label: Label): Unit = {
    val nextLabel = try {
      label.k(label)
      None
    } catch {
      case g: GotoThunk => Some(g.label)
    }
    if (nextLabel.isDefined) executeFrom(nextLabel.get)
  }

}

To use this code, you would first call label to get a Label object. You could then jump to the label by calling goto and passing the Label object as an argument.

Here's how it works.

Calling label captures the continuation with shift. We store the continuation in a Label object. When we run the continuation, the Label is passed as an argument. This allows it to be used by code within the continuation—by calls to goto, for example.

Calling goto throws a GotoThunk that contains the Label. We then catch the thunk. We can catch it because we made sure to run our continuation in a try/catch block. Once we catch the thunk, we extract its Label and run the Label's continuation, starting the process all over again. In this way we can continue calling goto indefinitely…

Goto is only one of many control flow operations that we can construct with delimited continuations. For example, we can make conditionals, loops, generators, coroutines, etc.

If you're interested in playing with the plugin yourself, you can find some brief usage instructions in my previous blog entry. Remember that the plugin is still under development! You may also wish to read a description of the plugin's status that was posted to scala-user by Tiark Rompf, the plugin's author.