One of the Racket tutorials actually goes into an example of using continuations to save application state for a web app (<a href="https://docs.racket-lang.org/more/index.html#%28part._.Continuations%29" rel="nofollow">https://docs.racket-lang.org/more/index.html#%28part._.Conti...</a>).<p>One issue with this approach is that it doesn't really scale easily beyond a single server. You need something like the JVM which allows for closures to be sent between machines sharing the same code base. Plus, even in the JVM case, you must have the class files required by the closure available on the JVM which tries to run it.<p>I really think it is a better idea to just use a database and pass state explicitly rather than trying to do something fancy with continuations. However, continuations can be extremely useful for making the server asynchronous without making it look asynchronous.<p>While Promises are nice, I think they are severely flawed in that they must "infect" any code which tries to use them. For instance, I was dealing with some Typescript compiler interfaces a few years back which expected to be able to read files synchronously, something which does not hold true if you try to emulate a filesystem in the browser using web requests. With true continuations, it would be possible to simply pause this computation transparently and then resume it once the request was complete.
A framework that works with continuations is Seaside in smalltalk, it is a delight to work with it.
<a href="https://seaside.st" rel="nofollow">https://seaside.st</a>
As mentioned in the document, continuation passing style can at times be a little difficult to read. That being said I found a talk that using continuation passing style to provide typed routing. [1]<p>This won't be the most efficient way to perform routing in an application, but i found the implementation really simple to understand and the error messages for the end-user seem really clear as well. It also helps if the language used allows for embedding DSLs that are easy to read for the end-user. (could be macros in lisp/elixir, well named functions with a little sprinkling of infix operators in OCaml, Haskell etc)<p>A little show HN in the comments: I've been exploring this approach and others [2] for comparison, and although i've moved away from this style as I progress in learning more OCaml, it was a fun little exercise to explore a CPS based typed routing approach. [3]<p>[1] <a href="https://dbp.io/talks/2016/fn-continuations-haskell-meetup.pdf" rel="nofollow">https://dbp.io/talks/2016/fn-continuations-haskell-meetup.pd...</a><p>[2] <a href="https://github.com/anuragsoni/routes" rel="nofollow">https://github.com/anuragsoni/routes</a><p>[3] <a href="https://github.com/anuragsoni/routes/blob/0.1.0/src/routes.ml" rel="nofollow">https://github.com/anuragsoni/routes/blob/0.1.0/src/routes.m...</a>
Around the same period, in the telephony world, IVR (interactive voice response) systems entered the web universe with the VoiceXML W3C recommendation. It allowed IVR developers to write server-side web applications as ordinary web applications, the HTML being substituted by VoiceXML.<p>Given the very linear nature of an IVR dialog, it became clear that a continuation-based approach would greatly simplify development, as mentioned in the article.<p>The Nu Echo "Rivr" Java framework was created around this idea. However, since there is no native continuation in Java (yet!), it was approximated through thread-based coroutines.<p>The payoff for the developers is huge. It allows the developer to directly "map" a dialog specification to Java code. Abstractions can easily be introduced without having to create an explicit model for the state (the state is just the set of the variables and objects referred by the thread). This approach is much more flexible than state-machine based paradigms.<p>Even though all architectural issues mentioned here are valid (namely the lack of session-based fault-tolerance), it turned out to be somewhat manageable in real-life situations because in this type of system, there is a limited number of calls handled simultaneously and their average duration is typically a few minutes.<p>Rivr is still used today and we are currently defining mechanisms with HAProxy to implement no-downtime scenarios in Kubernetes.
Also from 2002 I believe, an example of a project that was doing this with JavaScript using Rhino, the at-the-time state of the art Java implementation of the language that supported capturing a continuation.<p><a href="https://cocoon.apache.org/2.1/userdocs/flow/continuations.html" rel="nofollow">https://cocoon.apache.org/2.1/userdocs/flow/continuations.ht...</a>
It should be noted that the owner/author of this website (<a href="https://thelackthereof.org/" rel="nofollow">https://thelackthereof.org/</a> and not the posted PDF) wrote a Perl <i>continuations</i> based web library/framework called Continuity.<p>- <a href="https://thelackthereof.org/Continuity" rel="nofollow">https://thelackthereof.org/Continuity</a><p>- <a href="https://metacpan.org/pod/Continuity" rel="nofollow">https://metacpan.org/pod/Continuity</a><p>Shame it is no longer under development. Found it very handy & enjoyable using it for projects in the past (by itself and sometimes with Squatting framework built on top of it). Hats off to Brock (<a href="https://news.ycombinator.com/threads?id=awwaiid" rel="nofollow">https://news.ycombinator.com/threads?id=awwaiid</a>) for the great work creating Continuity.
Many of the comments here seem worried that scalability issues are going to crop up everywhere as people start using this architecture in large, popular applications. That isn't going to happen. Stop worrying about that and enjoy it for the cool hack that it is.
Paul Grahams mentions Closures and continuation passing style in Viaweb here: <a href="http://ep.yimg.com/ty/cdn/paulgraham/bbnexcerpts.txt" rel="nofollow">http://ep.yimg.com/ty/cdn/paulgraham/bbnexcerpts.txt</a>
I am new to this, but isn't the idea of calling next() which is prevalent in frameworks like express.js, essentially similar to continuations? I may be wrong, but I would genuinely like to know.
Please don't design web applications like this. It's counter to the core ideas of HTTP and REST. It's just about as bad a design as is ASP shoveling all its state into POST requests.<p>Not to mention that you have to choose between either dealing with garbage-collecting continuations stored on the server (choosing between either breaking client bookmarks, or bloating the server with never-to-be-used junk), or worrying about the security implications of storing continuations on the client (remembering that a continuation is <i>arbitrary code</i> which will executed <i>on your server</i>).<p>And since you don't have a well-defined HTTP API, but rather one directly coupled to the structure of your source code, all those links will break every time you change your code.<p>This design was notably promulgated by the Racket (then Dr. Scheme) crowd, who were (and I assume still are) notoriously allergic to state and so used mechanisms like this to try to hide it.<p>Please don't try to hide state. Especially in truly stateful systems like HTTP and user interfaces. Embrace state. Minimize it, isolate it, document it, control it, model it, but embrace it.