Skip to main content

Having a Racket with Pictures and Continuations

Posted by cayhorstmann on March 22, 2011 at 8:50 PM PDT

In this blog, I describe how the Racket language provides fun graphics and a nifty web framework. The  former is great for beginning students, and the latter is helpful for grasping the mind-bending concept of continuations. ♦

My colleague, Stephen Bloch from Adelphi University, sent me a copy of his
book “Picturing Programs: An Introduction to Computer Programming”. (A
companion website is here.) His
book is very different from your usual CS1
textbooks. It
uses Scheme, not Java. (Actually a dialect of Scheme called Racket.) But it isn't like your usual Scheme book
either. Instead of manipulating numbers and lists, which can be pretty dull
stuff for students, it produces nifty graphics.

Within minutes, you can do things like this:

I like it a lot. The instant feedback with the interpreter is easy and fun.
The pictures show what is happening —in a way that numbers and lists simply
cannot.

But there is a problem with Scheme in a CS1 course. When you teach a
semester-long Java course, it takes weeks for every student to figure out how
to use the IDE, how to get rid of syntax errors, how to compile and run a
program, and how to process input and output. Only then does the question arise
whether a student has any aptitude at all for developing programs. With Scheme,
there is no syntax besides “match the parentheses”, and the same question
arises within an hour or so. Well before the drop deadline. Where I teach, a
class gets canceled if too many students drop...

This semester, I don't teach CS1, but I teach a second course in programming
languages. We cover the usual buzzwords: metaprogramming, continuations,
monads, actors, STM, etc., and study various languages that make the concepts
concree. I hesitated whether I should add Scheme to the mix (it's not one of
Bruce Tate's seven
languages
), but I wanted it for explaining continuations. So, I boldly went
ahead. After all, there is no syntax besides “match the parentheses”, and
the students already know functional programming in Scala. I designed a lab with
graphics
to make it all look easy.

How did it work out with the continuations? Actually, much better than I
expected. Lots of people find continuations confusing, and I don't think
learning
them in Scala
is the way to go. The type annotations and the limitations of
the CPS transform really get in the way.

Racket, on the other hand, offers a compelling use case with its
continuation-based web framework. It is one thing to read about
it
, and quite another to experience it with your own hands. In a matter of
minutes, I wrote a Racket web application that

  • asks the user to provide a number and click Submit
  • asks the user to provide a second number and click Submit
  • displays a page with the result

The code:

(define (start req)
  (mk-result-page (+ (send-and-get "First number")
                     (send-and-get "Second number"))))

where mk-result-page formats the result and
send-and-get sends the form and gets the response. Details here...

The key is that there is a continuation inside send-and-get.
After sending the form to the browser, the web request is finished. When the
follow-on request comes in, a continuation is automatically invoked by the
framework, and processing continues inside send-and-get to fish
out the user input. If you are interested, check out this tutorial or
chapter 7 of this book
for more information.

Without much thinking, I gave my standard web assignment, to write a
program that

  • displays one multiple choice question per page
  • gets the user response from each page
  • after the last question, displays the score

In JSF, it is about 150 lines of code+markup, with a managed bean and two
JSF pages. In Rails, I had to modify 5 files in the generated scaffolding,
adding about 100 lines. (The JSF app is longer, but it is also better. Because
of conversational state, a user can take two instances of the quiz in two
browser tabs. I didn't know how to do that in Rails.)

I was blown way how handily Racket beat them both—45 lines of code+markup,
with no worries about page flow or state management. The main loop is
incredibly simple: Call send-and-get for each question and sum the
list of responses.

(define (start req)
    (mk-result-page (sum (map send-and-get questions))))

I realize that this technique doesn't necessarily scale, but I found it
impressive and somewhat mind-bending. If you have some bandwidth for
mind-bending exercises, give Racket a try! Don't worry about the syntax—there
isn't any except for “match the parentheses” ☺

Related Topics >>