Fact-checked by Grok 2 weeks ago

Continuation

In , a continuation is an abstract representation of the control state of a , capturing the remaining to be performed after a given point in execution, typically modeled as a that receives an intermediate and yields the program's final result. This concept reifies the program's dynamic execution context, such as the , allowing explicit manipulation of beyond standard function calls or returns. Continuations are foundational in functional programming languages, where they enable advanced control mechanisms through techniques like continuation-passing style (CPS), a transformation that explicitly passes a continuation argument to every function to dictate the next steps of computation. In CPS, a direct-style function like one computing a factorial is rewritten to accept both its original inputs and a continuation k, applying k to the result after performing the core logic, which facilitates optimizations such as tail-call elimination and avoids stack overflows in recursive code. For instance, the CPS form of a factorial function might define it as factCPS n k = if n = 0 then k 1 else factCPS (n-1) (λv. k (n * v)), explicitly threading control forward. The practical implementation of continuations often relies on primitives like call-with-current-continuation (call/cc), which captures the current continuation and passes it as an argument to a given , enabling non-local transfers such as coroutines, , or without traditional mechanisms. This operator, prominent in languages like and Racket, allows programmers to "escape" the normal flow by invoking the captured continuation, effectively jumping to an arbitrary point in the program while supplying a value. Continuations also serve as an in compilers for functional languages like ML or , aiding translations to imperative by making implicit explicit and supporting analyses for optimization.

Introduction

Definition

In computing, a continuation represents an abstract encapsulation of the remaining computation state at a particular point in program execution, delineating the control flow and pending operations from that point forward. It captures the dynamic context of the program, including elements like the call stack, return addresses, and environment bindings, effectively modeling "what happens next" after a given expression evaluates. Unlike traditional data structures, which store and manipulate values, continuations embody the execution itself rather than static data, enabling explicit over program flow without relying solely on implicit mechanisms. For instance, in languages supporting them, a continuation might include stack frames representing active calls and unresolved operations, distinguishing it as a of rather than payload. A useful conceptual illustrates this: imagine capturing the current program state as a continuation, then inserting arbitrary to execute in between, before resuming the original continuation to proceed as if uninterrupted—this "sandwiching" of computations highlights how continuations delimit and compose execution sequences. Continuations may be implicit in the runtime or, in more advanced cases, first-class entities that can be reified as manipulable objects, such as functions, for explicit passing and invocation. This notion relates briefly to lambda calculus, where continuations underpin continuation-passing style as a means to explicitly thread control through functional programs.

Core Concepts

Continuations represent the remaining computation of a program from a given point, effectively capturing a snapshot of the execution state to enable resumption at that precise location. In operational terms, this snapshot primarily involves the call stack, which records the sequence of pending function calls, along with associated live values such as register contents and the program counter needed to restore control flow. When a continuation is invoked, it restores this captured state, effectively jumping back to the resumption point while discarding or preserving the intermediate computation as required by the language semantics. This mechanism allows for non-local control transfers, such as full jumps, by reifying the dynamic context into a first-class entity that can be manipulated during execution. A key formalism for understanding and implementing continuations is (CPS), a transformation that rewrites programs to make explicit by passing continuations as additional arguments. In CPS, every receives not only its primary inputs but also a continuation parameter specifying the subsequent computation to perform upon producing a result, thereby eliminating implicit returns and enabling optimizations such as tail-call elimination. This style transforms direct-style code—where functions return values normally—into an equivalent form where all control is mediated through continuation applications, facilitating analysis and optimization of program behavior. The transformation can be formally described for a f(x) that computes a value v: it becomes \lambda k.\ f'(x, k), where f' is the transformed body incorporating the continuation k, and the result is passed to the continuation via (k\ v) to produce the final answer. f(x) \quad \Rightarrow \quad \lambda k.\ f'(x, k) Here, k maps the intermediate value v to the overall computation's outcome, ensuring that the entire program is expressed as a single, continuation-mediated expression. This preserves the original semantics while exposing the control structure, which is particularly useful for proving properties like adequacy in interpretations. From a theoretical perspective, continuations relate closely to denotational semantics, where they are modeled as mathematical functions that transform a computed value into the final answer of the entire program, providing an abstract way to specify control effects without referencing machine-level details. This approach, pioneered in early work on handling arbitrary jumps, treats the "rest of the computation" as a higher-order function over values, allowing denotations to compose modularly even in the presence of non-local control. In this framework, the semantics of a term M yielding value v is given by applying the continuation \kappa to v, yielding \kappa(v), which denotes the complete observable behavior. Such models ensure that continuations capture the essential flow of information and control in a composable, domain-theoretic manner.

History

Early Developments

The concept of continuations emerged in the early 1960s as an implicit technique for managing control flow in programming language implementations, prior to its formal naming or widespread recognition. In 1960, Steve Russell completed the first implementation of Lisp on the IBM 704 computer, hand-coding the evaluator in assembly language to support recursive function definitions without relying on a call stack that could overflow. This approach used explicit save and unsave routines on a single contiguous stack array to handle recursion, effectively passing control and environment information in a manner resembling modern continuation-passing style, though Russell did not term it as such. The Lisp 1.5 Programmer's Manual later described functions such as sassoc and search that operated using continuation-like mechanisms for association and pattern-directed invocation, enabling efficient recursion in early artificial intelligence applications. A more explicit early formulation appeared in 1964 with Adriaan van Wijngaarden's work on a for . Van Wijngaarden proposed transforming programs into to eliminate labels and statements, augmenting each procedure with an extra formal for the "specified label" and appending a to that at the procedure's end. This technique facilitated non-local control transfers in the preprocessor, supporting for handling alternatives in syntactic analysis and program transformation. Early applications of continuation-like ideas appeared in proving and within preprocessors during this period. In proving systems built on , such as those for geometric proofs around 1959–1961, recursive search with relied on explicit environment passing to avoid stack limitations, mirroring continuation concepts for exploring proof alternatives. Preprocessors for languages like employed with failure continuation mechanisms, inspired by tools like SNOBOL's pattern-directed processing, to resolve nondeterministic syntax and semantics efficiently. These developments were discussed at the IFIP Working Conference on Description Languages, held in , , from September 15–18, 1964, where van Wijngaarden presented his transformation as part of broader efforts to formalize language descriptions. The conference captured early explorations of such control structures, influencing subsequent work on language implementation.

Key Milestones

Peter Landin's development of the in 1964 provided an early abstract model for evaluating expressions, where the "D" (dump) register implicitly represented the continuation of computation as a stack of pending operations. This idea influenced subsequent work on control structures, including Landin's 1965 extension with the J operator, which embedded labels and jumps into values, foreshadowing explicit continuations. John C. Reynolds' 1993 historical survey highlighted these contributions as precursors to modern continuation concepts, tracing their evolution from operational models to semantic formalisms. In 1974, and Christopher P. Wadsworth formalized continuations in through their seminal paper, introducing the term "continuation" to denote the remaining computation after a given point in program execution. Their approach modeled full jumps and by treating programs as functions that accept and return continuations, enabling precise reasoning about non-local control transfers in lambda calculus-based languages. This work established (CPS) as a foundational technique for semantic analysis. The introduction of the call-with-current-continuation (call/cc) primitive in during the 1970s marked a practical milestone, allowing programmers to capture and manipulate the current continuation as a first-class value. Developed by Guy L. Steele Jr. and J. Sussman in their 1975 report on as an extended interpreter, call/cc provided a delimited way to implement advanced control operators like coroutines and directly in the language. During the 1980s and 1990s, continuations were advanced in concurrent and typed formalisms, particularly within the and . William D. Clinger's 1981 dissertation integrated continuations into actor semantics using continuous functionals to model dynamic behavior and nondeterminism in distributed systems. Concurrently, Albert R. Meyer and Mitchell Wand's 1985 paper on continuation semantics in typed formalized how continuations preserve and equivalence in higher-order functions, influencing design and .

First-Class Continuations

Uses

First-class continuations enable the implementation of coroutines, which facilitate by allowing programs to suspend execution at any point and resume later from the captured state. This approach provides explicit control over task switching without relying on preemptive scheduling, as seen in systems where continuations represent states in a that manages a ready . For instance, procedures like [yield](/page/Yield) and [spawn](/page/Spawn) can be defined using continuations to alternate between tasks voluntarily. Continuations also simplify by offering a non-local that unwinds the stack dynamically. Unlike traditional exceptions, which follow predefined handler chains, first-class continuations allow programmers to capture and invoke arbitrary points in the computation, enabling custom resumption after an error—such as restarting a or jumping to a recovery block. This is particularly useful in languages like , where dynamic-wind pairs with continuations to install and remove handlers during suspension and resumption. In search algorithms and parsers, continuations support by modeling non-deterministic choices and failure recovery without manual management. Constructs like amb use a fail of continuations to explore alternatives upon assertion failure, enabling "time-traveling" search that retries previous decisions, as demonstrated in solving problems like finding Pythagorean triples. This approach extends to parsers, where continuations allow efficient exploration of ambiguous grammars by capturing choice points. First-class continuations facilitate such as state machines by encoding execution states implicitly, avoiding the need for explicit stacks or finite state representations. The continuation itself serves as the current state, with resumption driving transitions, which simplifies modeling interactive behaviors like NPC actions in games. Similarly, patterns like the can leverage continuations for compositional traversal without altering object structures, aligning with functional styles of . In web frameworks, continuations address the challenges of stateless protocols like HTTP by capturing server-side computation states and serializing them for client-side resumption. This enables direct-style programming across requests, where primitives like send/suspend generate URLs tied to continuations, avoiding manual state passing; further details on web-specific applications are discussed later.

Examples

First-class continuations enable non-local control transfers in programming languages like through the call/cc , which captures the current continuation as a first-class . A classic example is computing the of a number x in (CPS), where call/cc supplies the initial continuation for the computation, allowing the result to be combined with subsequent operations, such as addition. The CPS form of is defined as \mathrm{factCPS}(n, k) = \begin{cases} k(1) & \text{if } n = 0 \\ \mathrm{factCPS}(n-1, \lambda v. k(n \cdot v)) & \text{otherwise} \end{cases} To add 10 to the of x, the expression (+ (call/cc ([lambda](/page/Lambda) (k) (factCPS x k))) 10) can be used, where the captured continuation k applies the outer after the computation completes. For instance, when x=0, it directly applies k(1), yielding 11; for x=3, the threaded continuations ensure the correct result of 16, demonstrating how explicitly passes control while call/cc integrates it with direct-style code. Continuations also facilitate coroutine implementations, simulating by alternating execution between multiple "threads" without operating system involvement. In , coroutines can be built using a of continuation objects to manage . For instance, a producer-consumer pair can be realized where one coroutine generates values and passes them to another for processing: the producer captures its continuation after producing a value and resumes the consumer's continuation, while the consumer does the reverse after consuming. This yields alternating output, such as printing successive integers like "0 1 2 ..." in an interleaved manner, effectively demonstrating cooperative scheduling akin to threads but fully under program control. A simpler illustration of capturing and invoking a continuation multiple times involves incrementing a by storing and reusing the continuation object. By capturing the continuation at a point that includes an increment operation and then invoking it repeatedly from different contexts, the program can accumulate increments across invocations, restarting execution from the capture point each time and abandoning the current —highlighting the one-shot nature per but allowing repeated use of the same object for iterative effects like counting. This approach underscores continuations' role in emulating loops or stateful computations without traditional or .

Implementation

First-class continuations are typically implemented in runtime systems by capturing and manipulating the program's state, often represented as the or an equivalent . One common approach is the stack-based , where the continuation is captured by copying or directly manipulating the current at the point of invocation. This method is efficient for escape continuations, which are invoked only once after capture, as it avoids heap allocation and leverages the native for fast resumption. However, it limits flexibility, preventing multiple invocations or reentrancy without additional mechanisms, since the original may be overwritten during execution. In contrast, heap-allocated continuations provide greater versatility by copying the relevant stack frames to the , creating a self-contained representation that can be invoked multiple times and supports reentrancy. This approach requires integration with the runtime's collector to manage the allocated continuation objects, ensuring they are reclaimed when no longer reachable. Heap allocation enables non-escaping uses, such as composing continuations or passing them across threads, but introduces overhead from copying and . The choice between stack-based and heap-allocated strategies involves key trade-offs in performance and capability. Stack-based methods excel in speed due to minimal allocation and direct hardware support for stack operations, making them suitable for systems prioritizing low-latency continuations. Heap-allocated continuations, while incurring copying costs—often 2-5 times higher than stack operations in empirical benchmarks—offer essential support for advanced features like multiple invocations, at the expense of increased pressure and collection activity. To mitigate the costs of copying, some implementations employ techniques, where the continuation is represented as a sequence of executable code pointers and data, avoiding deep copies by threading through the state incrementally. Alternatively, growth methods extend the dynamically during capture, preserving the original frames without immediate duplication, though this requires careful management to prevent unbounded growth. Many modern systems compile source code to (CPS) as an to facilitate these strategies.

Programming Language Support

Scheme and Racket provide native support for first-class continuations through the call-with-current-continuation (often abbreviated as call/cc) primitive, which captures the current continuation as a first-class value that can be invoked multiple times, enabling reinvocable continuations. Racket extends this with call-with-composable-continuation for delimited continuations, allowing more controlled capture and composition of continuation segments while maintaining first-class status. In Smalltalk, continuations are supported via blocks within the Seaside web framework, where blocks act as first-class continuations to manage state and across HTTP requests, enabling seamless handling of multiple independent flows without explicit state serialization. Haskell implements delimited continuations using the Cont from the transformers library, which transforms computations into (CPS) and supports operations like callCC for capturing and reinvoking partial continuations within a monadic context. This approach provides first-class delimited continuations without full undelimited capture, facilitating composable control effects in pure functional code. Lua emulates continuation-like behavior through its coroutine facilities, where coroutine.yield suspends execution and passes values, and coroutine.resume reinstates the coroutine from that point, simulating asymmetric transfers of control akin to basic continuations, though without direct first-class capture of the full stack. Recent developments in systems languages offer continuation-inspired features without full first-class undelimited continuations. In , the async/await syntax builds on futures to provide delimited continuation-like suspension and resumption, enabling structured asynchronous programming where futures represent capturable computation states, but lacking direct of arbitrary continuations. Go's goroutines, combined with channels for synchronization, emulate continuation passing through lightweight threading and message-based , allowing without explicit continuation capture. Swift's concurrency model includes CheckedContinuation types alongside async/await, supporting where continuations explicitly bridge callback-based APIs to async contexts, ensuring type-safe resumption within task hierarchies. For languages without built-in support, such as and , manual implementations in () allow simulating continuations by transforming functions to accept and invoke explicit continuation arguments, enabling custom like tail-recursive loops or asynchronous callbacks without native primitives.

Other Kinds

Escape Continuations

Escape continuations are a restricted form of continuations that enable one-shot, non-reentrant control transfers, allowing a to abruptly exit the current computational without resuming execution at the point of capture. Unlike full first-class continuations, which can be invoked multiple times and from arbitrary points, escape continuations are designed solely for escaping, effectively discarding the ongoing computation and jumping to a previously saved state. This mechanism mimics non-local gotos or exception unwinding but is explicitly tied to continuation semantics. In , escape continuations are implemented via the functions setjmp and longjmp, which are part of the <setjmp.h> header as defined in the (ISO/IEC 9899). The setjmp function saves the current execution environment (including the call and registers) into a jmp_buf object and returns zero; subsequently, longjmp restores that environment and transfers control back to the setjmp point, passing a non-zero value to simulate an alternate return path. This provides a way to perform non-local jumps across multiple frames, typically for error propagation. For example:
c
#include <setjmp.h>
#include <stdio.h>

jmp_buf env;

void second() {
    printf("In second\n");
    longjmp(env, 1);  // Escape to setjmp point
}

void first() {
    second();
    printf("End of first\n");  // Never reached
}

int main() {
    if (setjmp(env) == 0) {
        first();
    } else {
        printf("Returned via longjmp\n");
    }
    return 0;
}
This code demonstrates an early exit from second to main, bypassing the normal return from first. In functional languages like and its derivatives, escape continuations are captured using primitives such as call-with-escape-continuation (often abbreviated as call/ec). This function passes the current continuation (up to the dynamic extent) to a , which can invoke it to abandon the computation and resume at the capture point. A classic example in computes a list product by escaping early upon encountering zero:
scheme
(define list-product
  (lambda (s)
    (call/ec
      (lambda (exit)
        (let recur ((s s))
          (if (null? s) 1
              (if (= (car s) 0) (exit 0)
                  (* (car s) (recur (cdr s)))))))))
Here, exit serves as the escape continuation, terminating recursion and returning zero without further evaluation. In Racket, call-with-escape-continuation operates similarly but is scoped to the nearest prompt for efficiency and safety. Escape continuations find primary use in error handling and early exits within low-level or performance-sensitive code, where full continuation support would introduce unnecessary overhead. For instance, in C, they enable simulating exceptions in environments lacking built-in support, allowing cleanup or recovery from deep call stacks without structured alternatives like try-catch. However, their limitations are significant: they are strictly one-shot, meaning the continuation cannot be reinvoked after use, and invocation outside the original dynamic extent is undefined or prohibited, preventing storage or multiple applications. Additionally, they do not preserve or restore local state beyond the saved environment, potentially leading to resource leaks if not paired with explicit cleanup. These constraints make escape continuations unsuitable for composable or time-traveling control flows, confining them to simple escape scenarios.

Delimited Continuations

Delimited continuations capture a portion of the program's execution up to a specified , known as a , enabling partial and nested control over the flow without affecting the entire computation . Unlike undelimited continuations, which capture the full of the and typically abort the current upon , delimited continuations allow the captured to be composed and invoked multiple times within bounded scopes. This bounded nature facilitates safer and more by limiting the scope of control transfers. The primary operators for manipulating delimited continuations are reset and shift. The reset operator establishes a prompt that delimits the extent of any subsequent continuation capture, evaluating its argument within this bounded context and providing the result as the value of the entire expression. The shift operator, in contrast, captures the current continuation up to the nearest enclosing reset prompt and passes it as an argument to a function provided by the programmer, allowing explicit control over resumption. For instance, in a Scheme-like syntax:
(reset (+ 1 (shift k (* 2 (k 3)))))
This evaluates to 8: shift captures the continuation k = λx. (+ 1 x) up to reset, then the body computes (* 2 (k 3)) = (* 2 (+ 1 3)) = (* 2 4) = 8, which becomes the value of the reset expression. These operators multi-prompt variants for more flexible nesting. Delimited continuations are particularly useful for implementing generators, where the operation can be modeled as capturing and resuming a delimited context to produce values iteratively without full stack unwinding. In this framework, mainstream constructs in languages like or C# correspond directly to shift-like operations delimited by a generator's , enabling efficient coroutine-style . They also serve as a foundation for effects handlers, allowing structured management of computational effects such as , exceptions, or nondeterminism through composable abstractions that delimit effect propagation. This monadic encoding permits effects to be handled locally within prompts, avoiding global interference. Additionally, delimited continuations enable lightweight threads and coroutines by representing process contexts as capturable and resumable segments, facilitating in operating systems or user-space schedulers without the overhead of full context switches. For example, in a implementation, they support transactional operations by snapshotting and rolling back delimited execution states efficiently. Compared to full continuations like Scheme's call/cc, delimited variants offer safer compositionality, as their bounded scope prevents unintended captures of outer contexts and reduces risks such as stack overflows from repeated invocations. This makes them suitable for nested and modular designs, though they require explicit management. In , the transformer provides a way to simulate delimited continuations within monadic code. Additionally, since GHC 9.6 (2023), native delimited continuation primops are available for direct implementation.

Applications and Extensions

In Web Development

In web development, continuations provide a to handle the stateless nature of the HTTP protocol by capturing and resuming program state across multiple requests, allowing developers to write applications in a direct, procedural style rather than managing fragmented page states. This approach transforms the traditional request-response cycle into a suspended that can be reified and stored server-side, mitigating the need for manual state serialization in URLs, hidden form fields, or session variables. A key application is in frameworks like Seaside for Smalltalk, where continuations maintain application state within session objects, enabling seamless navigation and without losing context. For instance, in an checkout process, a continuation can suspend the current component upon user input (e.g., selecting payment details), store the state, and resume it later when the user returns via a callback, preserving local variables like cart contents across requests. This —where the server pauses execution on user interaction and resumes based on the incoming request—avoids the pitfalls of page-centric programming, such as conflicting state updates during concurrent flows. Christian Queinnec's work on continuation-based web programming exemplifies this by demonstrating how continuations enable multi-step interactions, such as a that captures the pending after the first number and resumes with the second, all without explicit state passing. Modern frameworks like Ocsigen in build on this, using () to treat user actions as selections among server-stored continuations, supporting typed, dynamic sites with features like remote function calls for forms and links. In Ocsigen, a service might register a continuation for a sequential input process, such as summing numbers from multiple form submissions, ensuring state integrity without client-side storage. The primary benefit is a shift to procedural coding, which circumvents "callback hell" in asynchronous and applications by composing interactions linearly rather than nesting callbacks for each event. This results in more modular, maintainable code, as seen in continuation-enabled systems that handle complex user flows—like back-button support or cloned sessions—without ad-hoc error-prone mechanisms.

In Linguistics

In linguistics, the continuation hypothesis posits that certain expressions, particularly quantifiers, denote higher-order functions that operate on their own continuations to resolve interactions. Introduced by , this approach treats quantifiers not merely as operators over individuals or sets, but as functions that manipulate the contextual "continuation"—the remaining semantic context—to determine how they interact with other elements in a . This framework addresses challenges in quantification by allowing expressions to dynamically influence their interpretive environment, providing a unified treatment of phenomena like displacement and . A key application of this is in handling ambiguity, where multiple possible arise from the relative scoping of quantifiers and anaphors. For instance, in the "Every farmer who owns a beats it," continuation-passing enables dynamic of the "it" to its antecedent within the scope of the universal quantifier "every," avoiding issues with static binding in traditional semantics. By passing continuations, the semantics can flexibly adjust the scope of the and the anaphor, yielding the intended reading where each farmer beats their own donkey, while also accommodating alternative interpretations if needed. This mechanism draws on to model incremental , ensuring that anaphoric dependencies are resolved in without requiring global reanalysis. The continuation approach also connects to formal semantic traditions, such as in "The Proper Treatment of Quantification in English" (PTQ), by reinterpreting meanings as that consume continuations rather than solely denoting truth conditions. In this view, a sentence's is a from its continuation (the expected contextual ) to a new continuation, allowing for more expressive handling of compositional semantics. Building briefly on , this extension facilitates analyses of complex interactions like and effects. Ongoing research applies continuation semantics to areas like underspecified semantics, where expressions leave multiple interpretations open, as seen in continuation-based formalizations of Abstract Meaning Representation (AMR) that encode contextual flexibility in predicate-argument structures. In dialogue systems, continuations support by modeling rhetorical relations and incremental updates, enabling robust handling of multi-turn interactions without full commitment to prior interpretations. These developments, with no major shifts noted after 2023, continue to influence theoretical and by bridging scope resolution with pragmatic underspecification.

Limitations

Disadvantages

One significant disadvantage of first-class continuations is their impact on code readability, as they enable non-local jumps that obscure the , resembling unstructured statements and making it difficult to trace program execution. For instance, in the esoteric language , which relies heavily on continuations via its c combinator, expressions become "hopelessly difficult to track down" due to unpredictable alterations in execution paths. This complexity has been critiqued as undermining the ability to reason about code, particularly when combined with imperative features like assignments. Debugging programs with first-class continuations presents substantial challenges, as the non-local nature of continuation invocations obscures traditional call traces and program state, complicating the identification of errors. The unpredictable resumption of continuations can lead to erratic behavior that defies standard debugging tools designed for linear or structured control flow. First-class continuations also introduce performance overhead, primarily from the need to capture and resume the stack, which often involves copying or heap allocation of activation records. In traditional stack-based implementations, capturing deep stacks can involve significant copying costs, though optimized models bound this overhead to a fixed depth to avoid unbounded growth, along with decreased locality of reference leading to cache misses and increased garbage collection pressure. Heap-based models further slow ordinary procedure calls due to non-contiguous memory access and additional linkage overhead. Moreover, the use of first-class continuations is error-prone, as they allow multiple invocations of the same continuation, risking infinite loops or resource leaks from improper . For example, repeatedly calling a captured continuation can create endless without clear termination, as demonstrated in code where a continuation is set and reinvoked indefinitely. Resource leaks arise when continuations prevent proper cleanup, such as leaving files open across unpredictable resumptions, exacerbating issues in dynamic environments.

Challenges in Adoption

One major barrier to the adoption of continuations in contemporary is the limited built-in support in mainstream programming languages as of 2025. Languages such as , Go, and lack native first-class continuations, instead providing async/await constructs that approximate delimited control transfer but fall short of the full expressiveness of capturing and manipulating arbitrary continuations. The steep learning curve poses another challenge, as mastering continuations demands a profound grasp of non-local and manipulation, which often overwhelms developers accustomed to more conventional paradigms and deters team-wide uptake. gaps exacerbate these issues, with libraries and tools underdeveloped for continuation-intensive codebases; moreover, integrating continuations with object-oriented designs or prevailing async patterns frequently results in awkward, error-prone constructs, such as difficulties in persisting state across invocations or avoiding memory leaks in dynamic environments. Recent developments in effect systems and algebraic effects, as seen in languages like Koka (v3.2.2 as of July ) and Effekt (active research with a dedicated in ), offer alternatives with modular effect composition without relying on raw continuation primitives, thereby diminishing the perceived necessity for traditional continuations in effectful programming.

References

  1. [1]
    [PDF] 1 Continuations - Cornell: Computer Science
    Continuations are a programming technique that may be used directly by a programmer, or used in program transformations by a compiler.
  2. [2]
    Continuation - HaskellWiki
    ### Definition of Continuation in Computer Science
  3. [3]
    2.9. Continuations and Continuation Passing - OpenDSA
    A continuation is a callback function k that represents the current state of the program's execution. More precisely, the continuation k is a function of one ...
  4. [4]
    [PDF] Some Notes on Continuations - CMU School of Computer Science
    15{212: Fundamental Structures of Computer Science II ... definition ... In this pattern of use we refer to the continuation cont as a success continuation.
  5. [5]
    [PDF] Typing First-Class Continuations in ML
    Nov 4, 1993 · The two new primitives are callcc, for call with current continuation, which takes a function as argument and calls it with the current ...Missing: original | Show results with:original
  6. [6]
    [PDF] Typing First-Class Continuations in ML
    The continuation represents the \rest of the computa- tion," and behaves as a function that takes the value of the expression as its argument and yields the ...
  7. [7]
    Reasoning about programs in continuation-passing style.
    Plotkin's λ-value calculus is sound but incomplete for reasoning about βeegr;-transformations on programs in continuation-passing style (CPS).
  8. [8]
    [PDF] From Folklore to Fact: Comparing Implementations of Stacks and ...
    ž A continuation represents this notion by capturing all of the values needed to continue execution, such as the call stack and other live values. For example, ...
  9. [9]
    [PDF] Theoretical Computer Science (1975) 125459. (Q Nort%IHolland ...
    The relation between call-by-value and call-by-name is then studied I)y giving simulations elf each lauguage by tba other and irlteryretations of each calculus ...
  10. [10]
    [PDF] History of Lisp - John McCarthy
    Feb 12, 1979 · A demonstration of LISP in a prototype time- sharing environment on the IBM 704 was made in 1960 (or 1961). (See. Appendix 2). L. Peter Deutsch ...
  11. [11]
    [PDF] The Discoveries of Continuations - Department of Computer Science
    In the early 1960's, the appearance of Algol 60 [32, 33] inspired a ferment of research on the implementation and formal de nition of programming languages.Missing: theorem pattern matching
  12. [12]
    [PDF] The mechanical evaluation of expressions - 1964 - Semantic Scholar
    SECD machine was the first attempt to make a computer use lambda- calculus in order to compute arithmetical expressions. ○. Two years after this article, in ...
  13. [13]
    [PDF] The discoveries of continuations
    In the early history of continuations, basic concepts were independently discovered an extraordinary number of times. This was due less to poor.
  14. [14]
    [PDF] Continuations: A Mathematical Semantics for Handling Full Jumps
    The purpose of this paper is to explain a method of giving the mathematical semantics of a programming language which includes a very general form of jump ...
  15. [15]
    Continuations: A Mathematical Semantics for Handling Full Jumps
    This paper describes a method of giving the mathematical semantics of programming languages which include the most general form of jumps, which includes ...
  16. [16]
    SCHEME: An Interpreter for Extended Lambda Calculus
    An interpreter for a LISP-like language, SCHEME, based on the lambda calculus [Church], but extended for side effects, multiprocessing, and process ...Missing: call/ | Show results with:call/
  17. [17]
  18. [18]
    (PDF) Continuation Semantics in Typed Lambda-Calculi (Summary).
    Oct 6, 2015 · PDF | On Jan 1, 1985, Albert R. Meyer and others published Continuation Semantics in Typed Lambda-Calculi (Summary).
  19. [19]
    Exceptions, time-traveling search, generators, threads, and coroutines
    Continuations permit the programmer to implement powerful language features and algorithms, including exceptions, backtracking search, threads, generators and ...
  20. [20]
    [PDF] Applications of Continuations - UNM CS
    BREAK is a fascinating example where the use of first-class continuations leads to an elegant ... For an example of blind backtracking with continuations see [11] ...
  21. [21]
    Representing control in the presence of first-class continuations
    Looping is accomplished by tail-recursive procedure calls, and sup- port for exception handling and “gotos” is provided by continuations. Continuations in ...
  22. [22]
    Continuations and concurrency | ACM SIGPLAN Notices
    Continuations have proven to be useful for implementing a variety of control structures, including exception handling facilities and breadth-first searching ...
  23. [23]
    Continuation API - GraalVM
    Backtracking in Search Algorithms: Utilizing continuations to represent states in search trees, allowing easy return to these states for further exploration.
  24. [24]
    [PDF] Programming Languages: Application and Interpretation - Brown CS
    Visitor pattern—to make it look more like a function-based ... consume two continuations, called success and failure continuations, and invoke one if.
  25. [25]
    [PDF] Implementation and Use of the PLT Scheme Web Server - Brown CS
    Our server takes advantage of Scheme's first-class continua- tions to provide servlet developers with a key primitive for creating interaction points: send/ ...
  26. [26]
    The scheme environment: continuations
    What we have done is to think about the computation of the factorial using the continuation model, only to revert to the direct model for reporting the result ...
  27. [27]
    Continuations and coroutines | Proceedings of the 1984 ACM ...
    Friedman, D.P., Haynes, C.T., Kohlbecker, E., and Wand, M. "The Scheme ... Continuations and coroutines. Software and its engineering · Software notations ...
  28. [28]
    [PDF] Representing Control in the Presence of First-Class Continuations
    First-class continuations represent the rest of computation from a point. This paper proposes a stack allocation approach to handle them, avoiding unbounded ...
  29. [29]
    [PDF] Formalizing Implementation Strategies for First-Class Continuations
    We consider the traditional strategy of stack-allocating all continuations by default, as if they were all second-class, and of copying this stack in case of ...
  30. [30]
    [PDF] An Empirical and Analytic Study of Stack vs. Heap Cost for ...
    The execution cost of stack and heap frames is similar, but heap frames are simpler to implement and allow efficient first-class continuations.<|control11|><|separator|>
  31. [31]
    [PDF] Implementation strategies for continuations - Semantic Scholar
    It is reported that Danvy's conjecture that continuation captures occur in clusters is somewhat true in the commercial setting of MacScheme+Toolsmith™, ...
  32. [32]
    call-with-current-continuation - Scheme Docs
    Alternation between coroutines is thus accomplished by saving and restoring the routines' continuations. Note that in this case, we can have two (or more) trees ...
  33. [33]
    10.4 Continuations - Racket Documentation
    Racket's support for prompts and composable continuations [Flatt07] closely resembles Sitaram's % and fcontrol operator [Sitaram93]. Racket installs a ...
  34. [34]
    [PDF] Seaside – A Multiple Control Flow Web Application Framework *
    Based on continuations, Seaside transparently manages the request/response loop and the handling of the necessary URLs, query strings and hidden form fields.<|separator|>
  35. [35]
    [PDF] A Monadic Framework for Delimited Continuations - Microsoft
    Then we need only to provide a Haskell library that defines a continuation monad CC, together with its basic return and >>= operators, and its control operators.
  36. [36]
    [PDF] 1 Delimited continuations in Haskell - okmij.org
    Delimited control, like its instance, exceptions, is an effect. Therefore, we have to use monads. We will be using the monad Cont from a monad transformer ...
  37. [37]
    [PDF] Coroutines in Lua
    Feb 16, 2004 · The basic idea in this implementation is to simulate symmetric transfers of control between Lua coroutines with pairs of yield/resume operations ...Missing: emulate | Show results with:emulate
  38. [38]
    9.1 – Coroutine Basics - Lua.org
    When we resume the coroutine, this call to yield finally returns and the coroutine continues its execution until the next yield or until its end: coroutine.Missing: emulate | Show results with:emulate
  39. [39]
    Crazy Idea: Coroutine Closures - Rust Internals
    Feb 10, 2015 · Generators have deep connections to delimited continuations and ... Help test async/await/generators/coroutines! announcements. 34, 22385 ...
  40. [40]
    Channel Use Cases - Go 101
    This article is to show as many channel use cases as possible. We should know that channel is not the only concurrency synchronization technique supported in ...Missing: emulate continuations
  41. [41]
    CheckedContinuation | Apple Developer Documentation
    A continuation is an opaque representation of program state. To create a continuation in asynchronous code, call the withUnsafeContinuation(function:_:) or ...Checkedcontinuation · Overview · Topics
  42. [42]
    Concurrency - Documentation - Swift.org
    Swift has built-in support for writing asynchronous and parallel code in a structured way. Asynchronous code can be suspended and resumed later, ...
  43. [43]
    By example: Continuation-passing style in JavaScript - Matt Might
    This article introduces CPS in both of its roles--as a style for non-blocking programming in JavaScript, and (briefly) as an intermediate form for a functional ...
  44. [44]
    [PDF] Implementing Escape Continuations in C
    Dec 14, 2023 · setjmp(env) memoizes the current environment into the env variable and returns 0. longjmp(env,val) starts over from the return point where env ...
  45. [45]
    What's in a Continuation - James Long
    May 17, 2016 · It's very important to understand that continuations only save the call stack, not any of the data that stack frames may reference.
  46. [46]
    Using setjmp and longjmp - Microsoft Learn
    Aug 3, 2021 · When setjmp and longjmp are used together, they provide a way to execute a non-local goto. They are typically used in C code to pass execution control to error ...
  47. [47]
    call/cc - Teach Yourself Scheme in Fixnum Days
    Scheme's nonlocal control operator is a procedure named call‑with‑current‑continuation . We will see how this operator can be used to create a breathtaking ...Missing: factorial | Show results with:factorial
  48. [48]
  49. [49]
    [PDF] Inverting back the inversion of control or, Continuations versus page ...
    A continuation is a program-level manageable value representing the rest of the computation of the program. “What to do next” is precisely what has to be ...Missing: 2003 | Show results with:2003
  50. [50]
    [PDF] Ocsigen: Typing Web Interaction with Objective Caml
    Sep 16, 2006 · Abstract. Ocsigen is a framework for programming highly dynamic web sites in Objective Caml. It allows to program sites as Ocaml applica-.
  51. [51]
    [PDF] Continuations and Aspects to Tame Callback Hell on the Web
    Dec 15, 2020 · Using general and multi-purpose concepts in programming languages, this paper proposes Sync/cc, a JavaScript package to prevent callback hell ...
  52. [52]
    The Unlambda Programming Language
    You're right: it's not very readable. Writing Unlambda programs isn't really as hard as it might seem; however, reading Unlambda programs is practically ...Missing: esolanguage critique
  53. [53]
    KMP's PFAQ: UNWIND-PROTECT vs Continuations (page 3)
    ### Summary of Kent Pitman’s Criticisms of Continuations
  54. [54]
    [PDF] First-Class Continuations on the Java Virtual Machine - POLITesi
    This section describes some implementation designed to implement first class continuations on the Java Virtual Machine. Heap based model. In a typical ...
  55. [55]
    Why async Rust? - Without boats
    Oct 15, 2023 · The basic issue at stake in this debate is Rust's decision to use a “stackless coroutine” approach to implementing user-space concurrency.The Development Of Async... · Green Threads · Futures
  56. [56]
    Continuations: What Have They Ever Done for Us? (Experience ...
    Here we report on the positives of this approach, as well as some challenges of using continuations, such as persisting data across requests, working with ...
  57. [57]
    [PDF] Programming with Continuations - Brown CS
    Since many languages (such as C and Java) do anyway, the program consumes memory unnecessarily. In an extreme case, a Java or C program that might have executed ...Missing: challenges adopting
  58. [58]
    [PDF] Algebraic Effects for Functional Programming - Microsoft
    We are going to demonstrate algebraic effects in the context of Koka – a call-by-value programming language with a type inference system that tracks effects.
  59. [59]
    Effekt: extensible algebraic effects in Scala (short paper)
    Algebraic effects are an interesting way to structure effectful programs and offer new modularity properties. We present the Scala library Effekt, ...