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