Delimited Continuations

I've become enamoured of delimited continuations. For the unenlightened, continuations in a high level language are equivalent to addresses you can shove into a program counter in a machine language --- i.e. a continuation is a jump target and is used for looping and for subroutine calls. In an assembly langauge you can create these addresses either as branch labels or using a opcode like ‘call’ or ‘jsr’ which pushes the current address into a register or onto the stack and then branches to a subroutine. Both the jump to the subroutine and the return address saved are continuations but the return address has the interesting property of being generated dynamically and saved as a data word. High level languages dont usually let you meddle with the flow of control like you can in an assembly language, but a few like the Scheme which support first-class continuations do, and the results can be incredibly powerful and just as unreadable as assembly language.

Scheme is a dialect of lisp and to handle the functional (lambda calculus) nature of the language continuations need to take a single argument to pass on the value that all lisp expressions (and hence all jump targets) must return. The call/cc command gives access to the continuation in the roundabout way of lambda calculus by realizing a lambda expression with the return continuation of call/cc expression.

(define (sgn x)
  (call/cc
    (lambda (return-sgn) ; ‘return-sgn’ is just a variable bound to the continuation
      (if ( x 0) (return-sgn +1))
      (return-sgn 0)
      (explode) ; we never explode
    )
  )
)

Here is a simple Scheme procedure that returns the sign of a number. Continuations are unnessesary to achieve this simple result but it demonstrates the basic idea of continuations; they are first-class objects that can be stored in a variable (here I used the variable name ‘return-sgn’) and in calling them you never return to the point of invocation. Continuations can also be aggregated into arbitrary data structures of any scope, may be invoked anywhere whatsoever, perhaps repeatedly to create loops. They can be called from deeply nested recursive procedures jumping out from the recursion in one step and conversely you can jump into a deeply recursive procedure from a previously saved continuation. Trying to follow the thread of execution can cause your brain to explode. Gotos are wimps when it comes to the obfuscation you can achieve with first-class continuations.

Delimited continuations are a refinement that go some way to improving the structure and readabilty of the code over what you would get when using the undeliminated variety.