F*dging up a Racket

(A small history behind the guide at http://hashcollision.org/brainfudge)

I was listening to Randal Schwartz give an interview to Matthew Flatt on FLOSS Weekly a few weeks ago. It was really cool to listen to Matthew, who consistently gave so much credit to the PLT team during the interview. At one point, the conversation turned toward the idea that Racket could support multiple languages. Randal asked, with excitement, whether that meant Racket could potentially do Perl 6. I was hoping that Matthew would respond with a “Dear God No!” kind of horror, but he took it in calm stride, of course, and said that people were welcome to try it if they had time.

That stuck with me. I wanted to do my part in helping to make such dreams/nightmares into reality. I definitely didn’t have the time to do it myself, not without getting severely schooled by my advisors. But I still wanted to help. Maybe I could write a guide to help other hackers get started. Hopefully, I’d get in less trouble that way.

So I wanted to write an extended example of how to add a new language to Racket. It needed to cover the entire gauntlet, from setting up the PLaneT development links, to writing the semantics and parser, to finally delivering a self-contained package on PLaneT. And I needed to use a non-parenthetical language.

Sometimes it’s hard to get across the idea that Racket supports multiple programming languages. The traditional examples that people see, such as programs written in Beginner Student Language:

#lang htdp/bsl ; Any key inflates the balloon
(require 2htdp/image) (require 2htdp/universe)
(define (balloon b) (circle b "solid" "red"))
(define (blow-up b k) (+ b 5))
(define (deflate b) (max (- b 1) 1))
  (big-bang 50 (on-key blow-up) (on-tick deflate)
               (to-draw balloon 200 200))

just aren’t convincing to people, precisely because it looks just like Scheme, with all those silly parentheses, defines, and all.

But something like this:

#lang planet dyoo/bf

… now there’s something deliciously perverse and screwed up about this! The choice was clear: the language had to be brainf*ck.

I spent an afternoon getting the code ready. For days, though, my brain was full of the document. Writing is hard! I wanted to keep the number of concepts down as much as possible. There were two dangers I tried to avoid:

  1. Losing velocity. A person needed to be able to read it in one sitting, or else they might give up too easily.
  2. Narrowing the target audience. I want to make it accessible to professional programmers with some familiarity with a programming language like Scheme. But they shouldn’t be Racket experts.

After some struggle, I finished the first nine chapters of the tutorial. I posted it up, and tried getting it on /r/programming. Although I failed miserably at getting upvotes, thankfully, more Reddit-savvy folks posted a compelling headline, and people started looking at the tutorial. Hurrah! Mission accomplished!

… except that some people were getting caught up by the fact that the implementation was slow. Drats. I went back and saw that I had messed up a small part of the implementation. I fixed it, but then saw that I had no choice: I had to extend the tutorial to show what I needed to do to fix the performance issues. A small matter of writing again, right?

There are moments in one’s life where certain actions seem preordained and inevitable. I had just gone and re-watched an anime, episode 10 to be precise, which involved a time loop and all sorts of pain, sadness, and suffering. The optimization section, Section 10, felt very much like the same thing: I needed to go back, fix things, and keep fixing things until the implementation performed reasonably well.

That section ended up being slightly longer than the first half of the document, and as long to write. The upside was that the tutorial felt much more complete after the writing was done. The downside was I didn’t get anything else done during the week. A conservation of hope and despair, I suppose.