Understanding Continuations in Racket | Schema Programming Part 11
If functional programming is a superpower, Continuations are time travel. They allow you to capture "what happens next" in a program, save it, and jump back to it later.
Advertisement
What is a Continuation?
Imagine you are executing a program. At any point, the "continuation" is the rest of the computation waiting to be done.
In (+ 1 (* 2 3)):
- When evaluating
(* 2 3), the continuation is "take the result, add 1 to it".
call-with-current-continuation (call/cc)
Racket exposes this primitive via call/cc. It takes a function of one argument (usually called k or exit).
Example 1: The "Eject Button" (Early Exit)
The simplest use is breaking out of a deep calculation (like return in C).
(define (search-for-zero lst)
(call/cc
(lambda (return)
(for ([x lst])
(when (zero? x)
(return "Found zero!"))) ; Jumps out immediately
"No zero found")))
(search-for-zero '(1 2 0 4 5)) ; Returns "Found zero!"
Example 2: Pausing Computation (Generators)
We can save a continuation to a variable and call it later!
(define saved-k #f)
(define (save-point)
(call/cc
(lambda (k)
(set! saved-k k) ; Save the continuation
"Saved!")))
(+ 100 (save-point))
If you run (+ 100 (save-point)), it sets saved-k and returns "Saved!". The result is 100 + "Saved!"? No, that would error. Let's fix the logic.
Actually, usually you return a value. (saved-k 5) essentially says: "Go back to where (save-point) was, and replace it with 5". So (+ 100 5) evaluates to 105.
Why use this?
- Coroutines: Cooperative multitasking.
- Backtracking: Implementing logic programming (like Prolog).
- Web Servers: Racket's web server uses continuations to handle stateless interactions (the "back" button problem).
Advertisement
Summary
call/cc captures the future of a computation. It is the primitive upon which exceptions, generators, and coroutines can be built.
What does calling a captured continuation do?
Md Nasim Sheikh
Software Developer at softexForge