SRFI 226: Control Features

by Marc Nieper-Wißkirchen

status: final (2023-04-25)

keywords: Continuations, Control Flow

See also SRFI 18: Multithreading support, SRFI 34: Exception Handling for Programs, SRFI 39: Parameter objects, SRFI 45: Primitives for Expressing Iterative Lazy Algorithms, SRFI 97: SRFI Libraries, SRFI 154: First-class dynamic extents, SRFI 155: Promises, SRFI 157: Continuation marks, and SRFI 158: Generators and Accumulators.


Whenever an expression is evaluated during the run of a Scheme program, there is a continuation awaiting the values of the expression. It is a distinguishing property of the Scheme programming language to offer a procedure (named call/cc) that captures the current continuation as a procedure, which, when called, aborts the then-current continuation and reinstates the captured one.

One can visualize a continuation as a list of (continuation) frames where a non-tail call adds a frame to the top of the list and where the return from a non-tail call removes the appropriate frame.

Moreover, each expression is evaluated in a dynamic environment that conceptually holds the values of parameters like the current output port and the dynamic-wind stack at the point of evaluation. As the dynamic environment is captured and reinstated along the continuation when the call/cc machinery is used, we can view it conceptually as part of the continuation.

The libraries defined in this SRFI are all concerned with continuations in a wider sense. More specifically, the topics are as follows:

Continuation Prompts
A continuation prompt is a special continuation frame that is tagged with a so-called prompt tag. Procedures to install continuation prompts and to abort the current continuation and escape back to a previously installed continuation prompt are provided. Moreover, continuation prompts are equipped with handlers that are invoked when a continuation is aborted to them.
When continuations are captured, the list of captured continuation frames is always delimited by some continuation prompt. This extends the semantics of Scheme’s call-with-current-continuation. Moreover, a procedure to capture so-called composable continuations is provided. As opposed to continuations captured by call-with-current-continuation, invoking a composable continuation does not abort the then-current continuation, so composable continuations behave like ordinary procedures. Together with continuation prompts, composable continuations allow one to implement the various proposed sets of control operators for delimited continuations. Finally, a primitive (call-in-continuation) is provided that allows calling a procedure in a given continuation instead of just delivering values to it.
Continuation Marks
Continuation marks are a provided feature that allows one to attach arbitrary information to continuation frames that is captured and reinstated along with the rest of the continuation. Conceptually, exception handlers and parameters are implemented in terms of continuation marks, but the syntax and procedures defined in this SRFI allow the user to use them in more general ways. Moreover, they reify the notion of a tail call, allowing one, for example, to test for tail context.
The exception mechanism of R6RS and R7RS is reinterpreted with respect to the concepts introduced in this SRFI. (Here, and in what follows we mean the so-called small language when we speak about R7RS.) Moreover, the with-exception-handler procedure and the guard syntax gain additional tail-context guarantees.
The parameter object mechanism of SRFI 39 and R7RS is reinterpreted with respect to the concepts introduced in this SRFI. Procedures to retrieve the current parameterization and to reinstall it later are provided. Moreover, the parameterize syntax gains an additional tail-context guarantee. To support an alternative model of parameters that is linked to the dynamic extent and not to the current parameterization, the notion of a parameter-like object and the temporarily syntax are introduced.
Fluids are a syntactic reinterpretation of parameter objects.
Delayed evaluation
The syntax and procedures on delayed evaluation of R7RS are revisited and redefined to handle the following satisfactorily: the parameterization of the delayed expression being forced, the treatment of exceptions raised during forcing of delayed expressions, and iterative lazy algorithms. Moreover, their semantics are detailed with respect to the concepts introduced in this SRFI, and promises can naturally deliver an arbitrary number of values when being forced. Finally, the initial continuation of a delayed expression being forced is defined in a way that makes it interchangeable with the initial continuation of a thread.
The thread mechanism of SRFI 18 is detailed with respect to the concepts introduced in this SRFI. In particular, mutation of parameter objects in multi-threaded applications is specified. In order to support timeout arguments in a type-safe way, a minimal API on time objects is included as well.

Large parts of this SRFI have been inspired by the control operators provided by Racket.