Continuations have been one of the features that I have been the most anxious to include in the 0.1 release of Ocean. Why? Quite simply because it is not done often enough. Most .NET/JVM implementations of Scheme offer half-hearted or no support for continuations. Scheme is, by nature, a very simple language. It seems almost paradoxical, then, that it has received as much attention as it has from the PL research community. The reason is simple. Its simplicity allows it to be used as a teaching tool (either by using a subset as a model language or by demoing code in Scheme), but it is its power that allows it to be useful to the researcher.
The power comes in a few forms. One is the mandated support for full numeric tower. Many languages include library support, but few include it built in. Another is the flexibility that hygienic macros allow. This allows the creation of new constructs in code that would normally have to be included in the compiler (switch statement anyone?). Yet another is in the use of first-class continuations.
This power is the difference between Scheme and VB. VB is simple, but weak, but Scheme is simple and powerful. So, one of the goals of Ocean is to ensure that both the simplicity and the power are maintained. I don’t want another Scheme-like scripting language. Nothing against them, but I want Scheme.
Anyway, now that I have explained why continuations are not a feature that I want to let go of (at least, not without a fight), the question becomes how to implement them. There is no built-in support for continuations in the ECMA 335. Mono has gone ahead and added them anyway. While this is terrific, I want Ocean to be fully compatible, to the maximum extent with all three of the platform implementations of which I am aware: Mono (by far, this one takes priority as it is more platform independent), Microsoft’s (the “canonical” one and, by far, the most important to the developer who wants to interact with commercial software), and GNU’s (the least important and, despite being almost the same age as Mono, the least mature for “real work”).
Because of this, I have been continually snooping around on the web and through academic papers. To date, I have found two possible methods and I am considering them both. The first, is good old fashioned CPS where some sort of custom class (that implements ICloneable) is used represent a continuation. Things could still get sticky with object references that are stored in classes that are bound in the continuation.
The second one I found is the more interesting. The paper is available here: http://www.ccs.neu.edu/scheme/pubs/stackhack4.html There is a lot of heavy lifting to be done, but the essential idea is to transform the programs so that they “build” the continuations themselves, as they execute, where each procedure must be modified to “co-operatively” (in the words of the authors) help to construct the continuation.
It is tough. CPS, in this case, would be slower as any reference will have to be tracked down with two “reads” instead of just one. Both seem like they could, potentially, have issues with nested references. The latter looks as though it would have a problem interfacing code compiled with this technique (Ocean, if that is the design route taken vs. code compiled in a C# compiler) according to the paper itself. CPS would not have this problem, however, because a continuation would become first-class in more than one meaning of the word. How are things going to be done? I don’t know. A third possibility that I am still considering is waiting until the next version (0.2) to implement continuations. I don’t like it, but it would get a useable piece of software released. And that, my friends, is my non conclusion. Hey, there was a reason that this article was dubbed a rumination.