Multiprompt delimited continuations
Jonathan Brachthäuser
jonathan.brachthaeuser at uni-tuebingen.de
Thu Sep 6 14:09:06 UTC 2018
Hey everybody,
first of all I want to say that I am really happy to see multiprompt
delimited continuations coming to the JVM. Thanks to all committers and
to Ron for all the great work! I experimented with the prototype and it
already works great.
While I see that the currently implemented API and programming model
works perfectly well with Fibers (which is your main motivation as I
understand), there are some issues that I would like to bring up.
# Continuations in Literature
Usually in literature "the continuation" represents the remainder of
a program. To briefly summarize some background, for instance, in
{
1 + callcc(k -> ... k.resume(3) ... );
System.out.println("Hello");
}
`k` is the (undelimited) continuation. It expects a value of type `int`
and represents the complete callstack at the point of calling `callcc`
-- including both the addition `1 + []` and the `println` statement.
On the other hand, with some notion of *delimited continuations*, we might have
reset(p1, () -> 5 - shift(p1, k -> k.resume(2) * 7));
which evaluates to `(5 - 3) * 7 = 21`. The continuation `k` corresponds
to the delimited evaluation context `5 - []`.
# Continuations in Loom
Since designed with fibers and threads in mind, continuations in loom
conflate multiple aspects of delimited continuations in one class:
- delimiting a continuation (`reset`). This is modeled by providing a
runnable to the constructor, which can also be thought of as the
initial continuation.
- capturing the continuation (`shift`). While capturing the continuation
is triggered by `Continuation.yield`, the actual continuation itself is
never really exposed. Instead, an object of type `Continuation` in
loom can be thought of as a **mutable reference cell** storing
the actual current (delimited) continuation.
- resuming a continuation (`resume`). When calling `Continuation.run`,
the current continuation, stored in the mutable reference cell, is
resumed and the cell is updated on yielding.
I am bringing this up for two reasons:
1) Conceptually continuations, as they are currently proposed, are closer
to coroutines than to continuations in the traditional sense. I don't
want to start bike shedding, but naming them "Continuation" can be
very confusing for people coming from a functional programming background.
2) The traditional interface of delimited continuations can be
implemented using the current proposal:
https://gist.github.com/b-studios/65e9e614f006d2125659267f6113efac#file-delimcc-java-L33-L37
However, in order to actually run a continuation to the end a recursive
function `runCont` is required and I couldn't yet find a non-recursive
implementation. This obviously will lead to unnecessary stack
usage. I am working on a library to program with algebraic effect
handlers in Java, which is based on multiprompt delimited continuations.
Project loom is very promising as a backend. However, the stack
usage of `runCont`, imposed by the current loom design is a blocker
since every yield will lead to an additional stackframe. Every
long running computation will thus eventually run out of stack space.
I would love to hear your thoughts on this.
Again, thanks to everybody working on this project and all the best,
Jonathan
More information about the loom-dev
mailing list