scala.util

continuations

package continuations

Delimited continuations are a feature for modifying the usual control flow of a program. To use continuations, provide the option -P:continuations:enable to the Scala compiler or REPL to activate the compiler plugin.

Below is an example of using continuations to suspend execution while awaiting user input. Similar facilities are used in so-called continuation-based web frameworks.

def go =
reset {
  println("Welcome!")
  val first = ask("Please give me a number")
  val second = ask("Please enter another number")
  printf("The sum of your numbers is: %d\n", first + second)
}

The reset is provided by this package and delimits the extent of the transformation. The ask is a function that will be defined below. Its effect is to issue a prompt and then suspend execution awaiting user input. Once the user provides an input value, execution of the suspended block resumes.

val sessions = new HashMap[UUID, Int=>Unit]
def ask(prompt: String): Int @cps[Unit] =
  shift {
    k: (Int => Unit) => {
      val id = uuidGen
      printf("%s\nrespond with: submit(0x%x, ...)\n", prompt, id)
      sessions += id -> k
    }
  }

The type of ask includes a @cps annotation which drives the transformation. The type signature Int @cps[Unit] means that ask should be used in a context requiring an Int, but actually it will suspend and return Unit.

The computation leading up to the first ask is executed normally. The remainder of the reset block is wrapped into a closure that is passed as the parameter k to the shift function, which can then decide whether and how to execute the continuation. In this example, the continuation is stored in a sessions map for later execution. This continuation includes a second call to ask, which is treated likewise once the execution resumes.

CPS Annotation

The aforementioned @cps[A] annotation is an alias for the more general @cpsParam[B,C] where B=C. The type A @cpsParam[B,C] describes a term which yields a value of type A within an evaluation context producing a value of type B. After the CPS transformation, this return type is modified to C.

The @cpsParam annotations are introduced by shift blocks, and propagate via the return types to the dynamically enclosing context. The propagation stops upon reaching a reset block.

Linear Supertypes
AnyRef, Any
Ordering
  1. Alphabetic
  2. By inheritance
Inherited
  1. continuations
  2. AnyRef
  3. Any
  1. Hide All
  2. Show all
Learn more about member selection
Visibility
  1. Public
  2. All

Type Members

  1. final class ControlContext[+A, -B, +C] extends Serializable

    This class represent a portion of computation that has a 'hole' in it.

    This class represent a portion of computation that has a 'hole' in it. The class has the ability to compute state up until a certain point where the state has the A type. If this context is given a function of type A => B to move the state to the B type, then the entire computation can be completed resulting in a value of type C.

    An Example:

    val cc = new ControlContext[String, String, String](
        fun = { (f: String=>String, err: Exception => String) =>
          val updatedState =
            try f("State")
            catch {
              case e: Exception => err(e)
            }
          updatedState + "-Complete!"
        },
        x = null.asIntanceOf[String]
    }
    cc.foreach(_ + "-Continued")  // Results in "State-Continued-Complete!"

    This class is used to transform calls to shift in the continuations package. Direct use and instantiation is possible, but usually reserved for advanced cases.

    A context may either be trivial or non-trivial. A trivial context just has a state of type A. When completing the computation, it's only necessary to use the function of type A => B directly against the trivial value. A non-trivial value stores a computation around the state transformation of type A => B and cannot be short-circuited.

    A

    The type of the state currently held in the context.

    B

    The type of the transformed state needed to complete this computation.

    C

    The return type of the entire computation stored in this context.

    Note

    fun and x are allowed to be null.

    See also

    scala.util.continutations.shiftR

  2. type cps[A] = cpsParam[A, A]

    An annotation that denotes a type is part of a continuation context.

    An annotation that denotes a type is part of a continuation context. @cps[A] is shorthand for cpsParam[A,A].

  3. class cpsParam[-B, +C] extends Annotation with StaticAnnotation with TypeConstraint

    This annotation is used to mark a parameter as part of a continuation context.

    This annotation is used to mark a parameter as part of a continuation context.

    The type A @cpsParam[B,C] is desugared to ControlContext[A,B,C] at compile time.

    B

    The type of computation state after computation has executed, and before control is returned to the shift.

    C

    The eventual return type of this delimited compuation.

    See also

    scala.util.continuations.ControlContext

  4. type suspendable = cpsParam[Unit, Unit]

    An annotation that denotes a type is part of a side effecting continuation context.

    An annotation that denotes a type is part of a side effecting continuation context. @suspendable is shorthand notation for @cpsParam[Unit,Unit] or @cps[Unit].

Value Members

  1. def reify[A, B, C](ctx: ⇒ A @scala.util.continuations.cpsParam[B,C]): ControlContext[A, B, C]

    This method converts from the sugared A @cpsParam[B,C] type to the desugared ControlContext[A,B,C] type.

    This method converts from the sugared A @cpsParam[B,C] type to the desugared ControlContext[A,B,C] type. The underlying data is not changed.

  2. def reifyR[A, B, C](ctx: ⇒ ControlContext[A, B, C]): ControlContext[A, B, C]

  3. def reset[A, C](ctx: ⇒ A @scala.util.continuations.cpsParam[A,C]): C

    Creates a context for continuations captured within the argument closure of this reset call and returns the result of the entire transformed computation.

    Creates a context for continuations captured within the argument closure of this reset call and returns the result of the entire transformed computation. Within an expression of the form reset { block }, the closure expression (block) will be modified such that at each call to shift the remainder of the expression is transformed into a function to be passed into the shift.

    returns

    The result of a block of code that uses shift to capture continuations.

  4. def reset0[A](ctx: ⇒ A @scala.util.continuations.cpsParam[A,A]): A

  5. def run[A](ctx: ⇒ Any @scala.util.continuations.cpsParam[Unit,A]): A

  6. def shift[A, B, C](fun: ((A) ⇒ B) ⇒ C): A @scala.util.continuations.cpsParam[B,C]

    The shift function captures the remaining computation in a reset block and passes it to a closure provided by the user.

    The shift function captures the remaining computation in a reset block and passes it to a closure provided by the user.

    For example:

    reset {
    shift { (k: Int => Int) => k(5) } + 1
    }

    In this example, shift is used in the expression shift ... + 1. The compiler will alter this expression so that the call to shift becomes a parameter to a function, creating something like:

    { (k: Int => Int) => k(5) } apply { _ + 1 }

    The result of this expression is 6.

    There can be more than one shift call in a reset block. Each call to shift can alter the return type of expression within the reset block, but will not change the return type of the entire reset { block } expression.

    fun

    A function where

    • The parameter is the remainder of computation within the current reset block. This is passed as a function A => B.
    • The return is the return value of the ControlContext which is generated from this inversion.
    Note

    Must be invoked in the context of a call to reset This context may not be far up the stack, but a call to reset is needed to eventually remove the @cps annotations from types.

  7. def shiftR[A, B, C](fun: ((A) ⇒ B) ⇒ C): ControlContext[A, B, C]

    Captures a computation into a ControlContext.

    Captures a computation into a ControlContext.

    fun

    The function which accepts the inverted computation and returns a final result.

    See also

    shift

  8. def shiftUnit[A, B, C >: B](x: A): A @scala.util.continuations.cpsParam[B,C]

  9. def shiftUnit0[A, B](x: A): A @scala.util.continuations.cpsParam[B,B]

  10. def shiftUnitR[A, B](x: A): ControlContext[A, B, B]

Inherited from AnyRef

Inherited from Any

Ungrouped