39. Metaprogramming, Or How I Learned To Stop Worrying And Let The Computer Write Code
John, my producer, rounded up a first rate crew and talented local actors for the video production the game would require. Given his experience as a commercial producer, he had many connections. He also booked a sound stage for the one-day shoot, and we had props and wardrobe made.
My downstairs neighbor at the time worked in wardrobe for the film industry, so she made us custom spaceship crew uniforms based on the excellent concept art, and they looked as good as anything in the movie “Alien”, which was a favorite of mine and a touchstone for the project.
I remember having a surreal feeling as we began our table read of the screenplay. This was the first time I had heard actors speak my words. But by the end of the read, hearing my words spoken aloud felt natural.
As a first-time director, I was in John’s capable hands. We had meetings with the DP and production designer, and he scheduled and arranged everything.
On the day of the shoot, everything went as well as I could have hoped for. The crew and actors were wonderful, upbeat, and professional. We shot on schedule and wrapped on time.
For the technically inclined, we shot on D1 format digital video, with eye to needing to do green screen in post production.
I had discovered a new venue for storytelling, and the desire to write and direct films was one which would stay with me for the next twenty years.
Code & Design
Writing GUI code such as dialog boxes for creating and editing objects typically involves a lot of boilerplate code. To me, this calls for Common Lisp macros supported by the language’s introspection and reflection facilities.
Macros are often touted as one of Lisp’s biggest strengths, due to the homoiconicity of the language. That’s a ten cent word which describes a language where the code is also data, and can be processed and generated using macros. Another term for this is metaprogramming, another fine high-value word.
I find writing macros satisfying and somewhat nerve wracking at the same time. As I start diving into deeper and deeper macro code, I can't help but wonder whether I'm doing the correct thing or just creating highly obfuscated code which I will be unable to understand two weeks from now.
In the listing above, the first line (in bold) is a macro call which generates the two functions below it. The macro takes a class name, a list of slot names and types, and produces the code for both the object creation and editing dialogs.
I find it hard to resist the urge to keep going deeper with macros. There is always more the computer can figure out and more ways of generalizing the code it writes. For example, in the case above if I were to specify types for the slots in the class definitions of the shapes, the macro could look those up and I wouldn't need to specify them myself.
The real satisfaction comes once the macros are written and debugged, and I can just type:
and several pages of code are generated behind the scenes, implementing two new dialog boxes for the
sine-curve-shape class with no additional effort on my part.
The feeling I have when I use macros is that of telling the computer what I want and having the computer do the work for me. Like having an assistant in the computer. Makes me feel kind of spoiled. And yet it also feels right somehow, as if that is how things are meant to be.
I also wanted to point out this line of code, which makes use of CLOS’s introspection abilities:
(SLOT-DEFINITION-INITFORM (FIND-CLASS-SLOT 'CIRCLE-SHAPE 'DIAMETER))
This code is used in the object creation dialog, and gets the default value of the
diameter slot from the class definition of
This illustrates an important point about Common Lisp: its power doesn’t just come from isolated features, but from the way in which the features have been designed to work together. The power of the language is greater than the sum of the powers of its parts.
And this reflects well on the language standard, showing how well thought out it is.