Build fluency in the vocabulary of a function invoking a continuation with its result instead of returning directly.
0 / 5 completed
1 / 5
At standup, a dev mentions writing functions that never return a value directly, but instead take an extra argument, a continuation function, and invoke it with the result once the computation finishes. What is this programming style called?
Continuation-passing style, or CPS, is exactly this: instead of a function returning its result directly to its caller, it takes an extra argument, a continuation function representing what to do next, and invokes that continuation with the result once its own computation finishes, rather than ever returning in the traditional sense. A hash collision is an unrelated hash-table concept about two keys sharing a bucket. This invoke-the-continuation-instead-of-returning structure is exactly why continuation-passing style makes the entire remaining flow of a program explicit as a chain of continuation calls.
2 / 5
During a design review, the team writes an asynchronous pipeline in continuation-passing style specifically so each step's continuation explicitly represents everything that should happen after that step completes. Which capability does this provide?
Writing the pipeline in continuation-passing style provides an explicit, first-class representation of what happens next after any given step, since the continuation is itself a function that can be passed around, stored, or invoked later just like any other value, making the remaining flow of the computation an explicit, manipulable part of the program rather than something implicit in the call stack. A plain function that returns directly to an implicit caller keeps that next-step information tied to the call stack rather than expressed as an explicit value. This explicit-next-step-as-a-value structure is exactly why continuation-passing style underlies techniques like implementing complex control flow or compiling asynchronous code.
3 / 5
In a code review, a dev notices a compiler-internals explanation describes a language's asynchronous await expressions without ever mentioning that they're commonly implemented by transforming the code into continuation-passing style under the hood. What does this represent?
This is an incomplete explanation missing continuation-passing style, since many compilers implement asynchronous await-based control flow precisely by transforming the code into continuation-passing style under the hood, turning each step after an await into an explicit continuation function rather than leaving that transformation unmentioned. A cache eviction policy is an unrelated concept about discarded cache entries. This omit-the-underlying-transformation pattern is exactly the kind of gap a reviewer flags in a compiler-internals explanation that's meant to describe how asynchronous code actually gets compiled.
4 / 5
An incident report shows a team struggled to debug a compiler-generated stack trace from asynchronous code, because they didn't recognize that the compiler had transformed their await-based code into continuation-passing style, making the generated stack frames look unfamiliar. What practice would prevent this?
Understanding that the compiler commonly implements asynchronous control flow using continuation-passing style explains why the generated stack frames look unfamiliar, since they correspond to continuation functions rather than a one-to-one mapping of the original source structure, which is exactly the missing context that would have prevented the debugging confusion in this incident. Continuing to debug with no awareness of this transformation regardless of how unfamiliar the frames look is exactly what caused the confusion to persist. This awareness of the continuation-passing-style transformation is genuinely useful background for debugging compiler-generated code from asynchronous language features.
5 / 5
During a PR review, a teammate asks why continuation-passing style is useful as an internal compiler technique even though almost nobody writes application code in that style directly. What is the reasoning?
Continuation-passing style makes control flow, including complex cases like suspending and resuming an asynchronous computation, explicit and mechanically transformable, which is exactly the property a compiler needs to systematically implement higher-level language features like async and await under the hood. That same explicitness makes continuation-passing style verbose and unnatural for a person to write directly, which is exactly why it's rarely used as an application-level programming style even though it remains a genuinely useful internal compiler technique.