A language for stateless web programs

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:

#lang web-server

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 racket, right?

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.

The 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 #lang instead.

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.