While digging deep into Racket’s web server for my forthcoming book, I’ve come to appreciate the genius of Racket’s philosophy of language-oriented programming. LOP is an idea that can show up in a number of ways, and one of the ones I’m especially fond of is
web-server, the language for stateless web programs.
Stateless servlets (
servlet being the Racket term for HTTP request handlers) are presented to you in the form of a new programming language,
web-server. Your web programs start like this:
This language looks just like plain Racket. The syntax is the same, and it even seems to have the same semantics. Example from the excellent Continue tutorial:
(define (render-greeting a-name) (response/xexpr `(html (head (title "Welcome")) (body (p ,(string-append "Hello " a-name))))))
(This example is written in the
web-server/insta language.) In the documentation on stateless servlets, it even says, concerning
web-server/base, that it
exports all of the functions and syntax from .
racket/base and nothing else
So why the fuss?
web-server is essentially just
Here’s what’s going on. When you run
web-server programs, they get transformed, behind the scenes, in a clever way so that continuations in web programs become serializable—that is, can be turned into URLs—which is what makes the idea of
continuations for the web much more practical, and certainly gives it a boost compared to the previous stateful servlets.
web-server language wasn’t invented just to make something cool. It isn’t just a thin wrapper around the Racket language, as though one could have easily done the same thing with a handful of functions, but choose to present them in the form of a
A #lang is used to solve a practical problem arising from doing continuation-based web programming. Prior to the
web-server language, continuations in the Racket web server had to be stored entirely on the server. Doing so led, in many cases, to huge memory consumption. Programming with continuations is great, but one apparently needs to pay a heavy price for it.
The language-oriented solution to this pressing problem isn’t a function or new data type, nor even a clever macro or two. It’s a new language whose main claim to fame is that it supports serializable continuations. Doing this means that the continuations, which previously had to be stored on the server, can now be encoded entirely in URLs, leading to a massive
unburdening of the server. To realize this solution, you write your web programs not in
racket (old), but in
web-server (new). That means that your whole program—everything, not just the cool, web servery-y bits like
send/suspend/dispatch & friends—gets suitably transformed so that it’s ready material for serializabling continuations.
I find that a brilliant illustration of the power of Racket #langs.