1. Continuation = “the rest of the computation”
While evaluating an expression, the remaining work waiting for its value is called the continuation. For example, while computing 2 * 3 in 1 + (2 * 3), the continuation is “add 1 to whatever value comes back” (v => 1 + v).
2. How reset and shift work
reset(() => ...) establishes a delimiter (boundary). Calling shift(k => ...) inside it captures the computation from the shift site up to the nearest enclosing reset as a function k, and passes k to the handler.
If the handler returns without calling k, the rest of the computation inside reset is discarded.
Read about the basic example
3. Why “Delimited”?
Traditional undelimited call/cc (as in Scheme) captures the entire rest of the program, and invoking it jumps without returning to the caller. In contrast, shift / reset captures only up to reset, so k behaves like a normal composable function that returns a value (and can even be used to build call/cc itself).
4. Notes for this playground
- Multi-shot and shared state: This playground runs in multi-shot mode, allowing the same continuation to be resumed multiple times. Only control state (execution frames up to
reset) is duplicated; variables and objects created before shift are shared and never rolled back.
- Experimental synchronous JS extension: Capturing is supported across normal synchronous JS calls, excluding
async, generators, active iterators, and finally cleanup on discarded continuations.
Select a title to open that example in the editor.