I've never figured out what makes "delimited" continuations different
from general continuations except that the implementation constrains
where a "delimited" continuation may be invoked. But that seems to be
a difference in usage rather than in kind.
Full continuations are, conceptually, a copy of the whole stack, wrapped
as a kind of function that never returns.
Delimited continuations offer, conceptually, a copy of a chunk of the
stack, wrapped as a kind of function that does return.
=== Stefan
On Sun, 20 Sep 2026 16:31:49 -0400, Stefan Monnier
<monnier@iro.umontreal.ca> wrote:
I've never figured out what makes "delimited" continuations different
from general continuations except that the implementation constrains
where a "delimited" continuation may be invoked. But that seems to be
a difference in usage rather than in kind.
Full continuations are, conceptually, a copy of the whole stack, wrapped
as a kind of function that never returns.
Delimited continuations offer, conceptually, a copy of a chunk of the >>stack, wrapped as a kind of function that does return.
=== Stefan
I appreciate the explanation ... but I'm a bit dense and I don't see
what delimited continuations give you vs just creating the equivalent closure.
I look at continuations from the POV of a compiler writer: I see them
as co-routines. Calling a co-routine is a "sideways" jump into a
different call chain. If the co-routine is to finish and return, then obviously its originating call chain must be preserved.
You mentioned above that DCs are wrapped in a function, so they can
finish and "return" [for some definition].
But if the intent of keeping the stack is simply to allow the
[co-routine] entry point to be in a nested function ... well then it
seems that having the compiler perform closure conversion would get
you to a result equivalent to the DC without needing to preserve the
runtime call stack - which typically contains (lots of) extraneous
state unrelated to the needs of the closure.
Dunno. Perhaps implementations that heap allocate stack frames just
don't bother with closure conversion, choosing instead to waste the
address space and eat the extra GC processing.
Delimited continutaions [...]
(That creates issues for scoped-based resource and other
scope-based things.)
Kaz Kylheku <046-301-5902@kylheku.com> wrote:
Delimited continutaions [...]
You've just made delimited continuations make sense to me for the first
time: thank you!
(That creates issues for scoped-based resource and other
scope-based things.)
If I understand this right (and this agrees with the mental model I've
built from all the excised bits of your post) this means that you still
need things like dynamic-wind with delimited continuations, and various resource-scoping problems are not solved by them.
(block foo (unwind-protect (return-from foo 42) (prinl "cleanup!")))"cleanup!"
(block foo (unwind-protect (sys:abscond-from foo 42) (prinl"cleanup!")))
But they sound hugely better than standard Scheme-style continuations. If
I didn't have a cat sitting on me I'd go up & play with them right away (I think Racket has them).
So to reiterate, I have not solved the resource problem for the
low-level DLC's; there is no dynamic wind. But we have a working
solution for thread-like abstractions built on top of DLC's.
(Abstractions which do not reuse a continuation; do not repeat/replay
the same captured computation.)
(defun yflatten-rec (obj)(cond
(defun yflatten (obj) (yflatten-rec obj))yflatten
(defvar fn (obtain (yflatten '(1 2 (3 4 (5) 6)))))fn
[fn]1
[fn]2
[fn]3
[fn]4
[fn]5
[fn]6
[fn]t
(trace yflatten-rec)nil
(defparm fn (obtain (yflatten '(1 2 (3 4 (5) 6)))))fn
[fn](yflatten-rec ((1 2 (3 4 (5) 6)))
[fn]nil)
[fn]nil)
[fn]nil)
[fn]nil)
[fn]nil)
[fn]nil)
Each time we call [fn], a new delimited continuation is used,
which was prepared ahead of time by the previous yield-from
(or the initial obtain). The replacement of one delimited
continuation by another inside the fn object is destructive:
it has a single context, just like a thread's instruction pointer
being destructively updated.
On Tue, 22 Sep 2026 19:03:18 -0000 (UTC), Kaz Kylheku
<046-301-5902@kylheku.com> wrote:
... about delimited continuations ...
Hi Kaz,
Apologies for the delay - it's been one of those weeks.
I want to thank you for expounding on your explanation. I think I
understand better now, but I'm going to have to play with it a bit.
It would help greatly if I could look inside a compiler / runtime at a
real implementation. Decsriptions are fine, but seeing it done is how
I learn best.
| Sysop: | Amessyroom |
|---|---|
| Location: | Fayetteville, NC |
| Users: | 74 |
| Nodes: | 6 (0 / 6) |
| Uptime: | 03:37:11 |
| Calls: | 1,194 |
| Files: | 1,353 |
| D/L today: |
2 files (1,590K bytes) |
| Messages: | 291,364 |