Installing LispBuilder

Run the following in your lisp interpreter (for me it's SBCL)

(asdf-install:install :cffi)

That command stops and asks a lot about not reading the GPG key and also needs to re-initialize the central registry for every new package. No big deal though, both are offered as restarts.

Next, check-out lispbuilder.

svn checkout http://lispbuilder.googlecode.com/svn/trunk/ lispbuilder-read-only

Put the following in ~/.sbclrc. You will have to change the paths to match where you checked out lispbuilder to.

(pushnew "~/src/lispbuilder-read-only/lispbuilder-sdl/" asdf:*central-registry* :test #'equal)
(pushnew "~/src/lispbuilder-read-only/lispbuilder-sdl-mixer/" asdf:*central-registry* :test #'equal)

(asdf:oos 'asdf:load-op 'lispbuilder-sdl)
(asdf:oos 'asdf:load-op 'lispbuilder-sdl-examples)

Running (lispbuilder-sdl-examples:mandelbrot) yields a window drawing a mandelbrot, so it must have installed.

There is a really good user manual with examples and line-by-line explanations.

Using the REPL

A primary inspiration trying out lisp with emacs/slime is Bret Victor's talk on interactive programming. My distaste for the compile-test-modify cycle grew last semester when I had to compile C++ using Visual Studio … over a network. 12-second compile times were the norm. That and a bug in VS 2010 kept auto-complete from working in the Windows forms mode, combined with a stunning lack of quality documentation for the C++ Forms libraries turned the projects into an agonizingly slow guess-and-check "development" process. Anyhow, back to lisp.

I loaded the following code from the wiki and stated executing it:

(defparameter *random-color* sdl:*blue*)
(defun mouse-rect-2d ()
  (sdl:with-init ()
    (sdl:window 200 200 :title-caption "REPL without a cause")
    (setf (sdl:frame-rate) 60)

    (sdl:with-events ()
      (:quit-event () t)
      (:key-down-event ()
       (sdl:push-quit-event))
      (:idle ()
       ;; Change the color of the box if the left mouse button is depressed
       (when (sdl:mouse-left-p))
;;         (setf *random-color* (sdl:color :r (random 255) :g (random 255) :b (random 255))))

       ;; Clear the display each game loop
       (sdl:clear-display sdl:*black*)

       ;; Draw the box having a center at the mouse x/y coordinates.
       (sdl:draw-box (sdl:rectangle-from-midpoint-* (sdl:mouse-x) (sdl:mouse-y) 20 20)
                     :color *random-color*)

       ;; Redraw the display
       (sdl:update-display)))))

There is a screenshot here basic\_sdl\_with\_repl.jpg

Then I changed sdl:*blue* to sdl:*red*, pressed C-c C-c, and boom! the color changed. Nice.

Okay, so a global variable can be changed on the fly. Big deal. Any debugger can do that. What about redefining a function, recompiling, and executing on the fly? To test this out, I wrote the function (defun my_clear () (sdl:clear-display sdl:*red*)). I then replaced (sdl:clear-display sdl:*black*) with (my_clear) in the main event loop. Then, once I ran it, I could change the color inside of my_clear, redefine the function with C-c C-c, and have the already-running process change accordingly. This is powerful.

There is a tip here on the lispbuilder wiki with a tip about keeping the repl available when running a single-threaded lisp/sdl program. I haven't needed this yet.