Playing with Nifty Assignments

I’ve been looking at Nifty Assignments. I thought it would be fun to look at the first assignment and see what it’d look like in Racket.

#lang racket
 
;; The Iron Image Puzzle
;; Part of the Nifty Assignments page by Nick Parlante.
;; http://nifty.stanford.edu/2011/parlante-image-puzzle/
 
;; We’ll use the 2htdp/image library for this one.
(require 2htdp/image)
 
;; First, grab the image by its url.
(define distorted-image
  (bitmap/url “http://nifty.stanford.edu/2011/parlante-image-puzzle/iron-puzzle.png”))
 
;; We will want to decompose the image into its individual pixels.  We can use
;; image->color-list to do this.
;; To make experimenting with the pixels an easy thing to do, let’s write
;; a function that will let us “map” across the pixels of an image
;; to get another image.
(define (image-transform an-image a-pixel-transform)
  (define colors (image->color-list an-image))
  (define new-colors (map a-pixel-transform colors))
  (color-list->bitmap new-colors
                      (image-width an-image)
                      (image-height an-image)))
 
 
;; With image-transform in hand, we can apply a filter,
;; such as zeroing out the blue and green components like this:
(define (zero-blue-green a-color)
  (color (color-red a-color)
         0
         0))
(define dark-image
  (image-transform distorted-image zero-blue-green))
 
 
;; The image is still a bit darkened.  Let’s bump up the red component
;; by a factor of ten.
(define (red*10 a-color)
  (color (* (color-red a-color) 10)
         (color-green a-color)
         (color-blue a-color)))
(define red-eye-image
  (image-transform dark-image red*10))
 
;; And now we should be able to look at red-eye-image and recognize
;; the landmark.

RacketCon

I’m still recovering from the week of Program By Design, followed immediately with RacketCon. My feet are meant for walking, not standing.

The weekend was fun, though. I got to show that Whalesong, my Racket to JavaScript compiler, is starting to do interesting things. Although I didn’t tell anyone explicitly, I was dogfooding Whalesong: my entire slideshow was itself a World program that I had compiled with Whalesong itself.

Unfortunately, I was so nervous during the beginning of the talk, that I rushed my example about a slideshow being itself a world program into incoherence. I’ll have to watch myself when the videos come out, grimace, and hope to do better next time. I think folks got a kick out of the JQuery example.

Other items to note:

  • The second day unfortunately suffered from a lack of air conditioning.
  • Jay McCarthy showed a kick-butt example of game programs written with World. My ears are still ringing with the thump of the video game music.
  • Marco Morazan showed how to teach A* to first-year undergrads. Awesome.
  • Matthew Flatt talked about the history and future of Racket. He brought his magic 8-ball with him.

Ok, better get back to work and get Whalesong ready…

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.