My recent adventures with Scheme (as of 2021) are a perfect example of the project rabbit-hole problem.
I had a project (a simple online store) which I could in theory have implemented in any programming language. I thought ‘why not try R7RS Scheme?’ Then I started building up a list of the things I’d need to implement myself in order to do that:
- A way to send basic HTTPS requests to the Stripe API. (I intended to use Stripe Checkout, so the lack of a full binding wasn’t so bad.) Actually, the Scheme implementation I intended to use had a library for doing HTTPS already, so I could just put some basic wrapping around that.
- I intended to use Redis as the ‘local’ backing store, with the source of truth being Stripe in most cases. (Stripe makes you create ‘price objects’ stored with them, and I didn’t want the price in the local database, but an API request to Stripe for the prices of things every page load seemed abusive.) So I’d need a way to talk to Redis; fortunately, the Redis protocol is nice and simple.
- … but Scheme lacks a good high-level networking interface! There’s only SRFI 106, which is a low-level wrapper on the POSIX/BSD socket API, including making you use special read and write functions on sockets rather than native Scheme ports. It provides a way to get input and output ports for a socket, but my Scheme implementation’s SRFI 106-esque socket library doesn’t actually provide that. That makes the Redis protocol implementation instantly way more difficult.
- Then, of course, I’d need a web application framework. I collected my ideas about this as Wibble. Alone it wouldn’t be too hard, but in context of all the other stuff I’d need to do …
- It’d be nice if that web application framework had a nice Scheme-y HTML templating system. That led me to implement
html-writer, which isn’t the complete system I have in mind (that will use syntax to provide template inheritance etc.) but is a good start.
That led down further rabbit holes, some of them caught up in dependency chains with things coming in R7RS that haven’t been completed yet:
- John Cowan has a preliminary spec for a high-level networking API, but it depends on keyword arguments. In order to avoid ending up with multiple incompatible keyword argument systems in R7RS Large, this means it’s stuck waiting fora keyword argument system to be agreed on. I asked John about it, and he said keyword arguments are in turn waiting for the more powerful macro system to be decided (
syntax-caseor explicit renaming macros, or what?). Marc Nieper-Wißkirchen is compiling all the options as SRFI 211, but it’s a big job, and he’s a busy man.
- I volunteered to implement the high-level networking API when it turns into a SRFI, and I thought a cool thing to have to demonstrate it might be a simple HTTP/1.0 server.
- Then I thought it would be cool to have something like Rack or WSGI to connect to that HTTP server. I collected my ideas on that as SWAG.
- Implementing HTTP nicely on top of network ports would require more functions for reading from a port than Scheme currently provides. John has a nice proposal for such procedures as well, which I implemented in about an hour.
For a 50 year old programming language, Scheme’s library support is still rather poor. (Actually it isn’t — there are libraries in lots of individual Scheme implementations which do quite a lot of what I want here. But they’re not portable, and no Scheme has a complete selection of the libraries I’d like to use. SWAG is a complete innovation in the Scheme world, as far as I know.)
The following directed graph (where every node is something I’d either have to write, or (in a few cases like the macro system) simply isn’t standardized yet, and the → link means ‘depends on’) shows how ridiculous the situation is: