Common Cold, my latest hack
When someone wants to try continuations-based web pages in Common Lisp, they're usually directed at UnCommonWeb. A lot of work has gone into making UCW powerful, but that's not necessarily useful, and can even make things harder to understand, when one doesn't need all that power. Common Cold tries to target that niche, as a simple library (I certainly wouldn't call it a framework) with a low cost of entry.
To keep things simple, Common Cold (CC) defers to third-party libraries for nearly everything. It uses Hunchentoot straightforwardly for web serving per se. Functions only have to return pages as strings, for example, using CL-WHO (which is what CC does internally). Moreover, instead of striving for a transparent restructuring of code to extract continuations, explicitly marked macros must be used by the user. Hopefully, they won't prove to be particularly painful.
Having the programmer annotate its code with special forms instead of using a codewalker has several advantages. Obviously, we can use the normal CL macro machinery instead of having to use a codewalker, which makes the code much less complex. It also makes the restructuring more transparent and controllable for the programmer. I believe the most important advantage, however, is simply that the border between continuations-ful code and normal CL code is always explicit. When playing with non-native but 'transparent' continuations, the abstraction tends to leak in various surprising ways (for example, when passing a continuation-capturing closure to an untransformed higher-order function), even more so when continuations are serialised, as in Common Cold.
Serialised continuations are another design goal of Common Cold. Continuations-based web systems usually keep the continuations server-side (for a certain amount of time), and only pass an unique handle to the client. This means that every request consumes server resources and that URLs always have a somewhat short lifetime. It also makes load balancing more difficult, unless continuations can be migrated from one node to another. CC instead uses special forms to enable serialisable closures (and continuation frames). They are then encoded in the URL, instead of a session id or of a handle. The system was designed so that even the deserialisation routines can be serialised, making migration and load balancing easier to implement. These continuation URLs have an illimited lifetime, as long as the webpage functions are not recompiled (and that could be arranged). They are thus closer to the ideal of cool URLs than those of typical continuations-based web frameworks.
Since serialising and deserialising closures and continuations amounts to deeply copying them, side effects to lexical bindings often make little sense. Dynamic bindings (special variables) are instead used for side-effectful bindings. Since special variables have a dynamic scope, capturing their latest value in continuations, which can be seen as capturing the current dynamic environment, seems to make sense. While assignment is restricted to special variables, it is far from discouraged. Common Cold establishes a parallel between CGI parameters and top-level (non-shadowed) dynamic bindings. Their values are always saved in the continuation URL. However, they may be overridden, as if by assignment, by CGI parameters with the same (symbol-)name. These parameters are also exposed in the URL to make them easier to manipulate. To simplify interactions via forms, only the rightmost binding for any given parameter is considered.
More on how to actually use Common Cold later; I have a conference to register at in 6 hours.
posted at: 00:00 | /Lisp/CommonCold | permalink