February 27, 2008

Imaginative, Aesthetic, Executable Writing

by Nick Montfort · , 12:20 pm

I just wrote up some notes toward a talk at the Codework workshop at WVU. I figured I’d drop them in here, for those interested in the aesthetics of programming and the relationship of programming and creative writing.

I start with a difference between computer programming and what is traditionally called creative writing: Code has both a human meaning and a formal machine semantics, while creative writing in the usual sense has only human meaning — it cannot be compiled and executed on a computer.

By “machine semantics,” I mean that the program has a meaning because of how it runs on a machine, a computer. This idea is a commonplace of research in programming languages. A specific formulation of this type of semantics, for instance, is the operational semantics, which can be used to prove properties of programming languages. I am not claiming that the computer is a device that makes meaning for itself or that programs are meaningful to computers, only that they have this different sort of meaning because they are instructions that cause machines to operate.

In using the term “human meaning,” I am stating that a person can read a computer program and make sense of it. To do this, the person must run the program in his or her mind to some extent, simulating what the computer would do and understanding it. This relates to the program’s machine semantics. But there are also features of the program that have no meaning in terms of how the program operates, but which do signify to people. Variable names, the names of functions, subroutines, methods, labels, and so on, and comments are some of these features. The choice of a particular way of writing code when there are several equivalent options (using “while” instead of “redo” in Perl, for instance, or a more or less “Pythonic” way of doing the same thing in Python) also allows programmers to determine style and signal meaning to people.

Programs are typically read by many people. They will certainly be read by the programmer as the program is initially written, expanded, refactored, and revisited. They will be read by managers and collaborators. They will be read by people working to port the program to a new platform, package it for distribution, or fix bugs. And of course they may be read by people learning about programming or just curious about the workings of the particular program. Given this readership, the human meaning of code is not insignificant on a practical level, and programming practices have acknowledged this.

Because these two aspects are present and are particular to code, the interplay between them is particularly interesting, and, in fact, I believe it is the locus of a new type of creative writing practice in which code itself is the thing written. That is, programming does not inform creative writing or vice versa; the same activity is, completely, both a programming practice and a creative writing practice.

Here are some programming practices and a description of how they engage these two levels of meaning:

Refactoring. The process of revising a program so that it is streamlined, clear, and meets coding guidelines or “best practices.” This mainly engages the level of machine semantics, at least in most of my refactoring, but it also deals to some extent with the level of human meaning because comments may be added and the program may be reorganized for the purpose of better understanding. However, the changes being made in refactoring are usually straightforward, aimed at better engineering and adherence to standards. There may be an art of programming, but it is hard to see refactoring as an imaginative or poetic process.

Compression. This is undertaken by those participating in Perl Golf, where the object is to write a program in as few “strokes,” or keystrokes, as possible. The problem to be solved is fixed and the goal is to accomplish a solution with extreme economy in program size. This mainly engages the level of human meaning — and then, only as a side effect. Compressed programs must all do the same task, so their machine semantics must be the same, but shorter ones will often (not always) be significantly harder to understand. Analogies can be drawn to constrained writing and competitive traditions of poem-writing, but, for different reasons than with refactoring, it is difficult to see this practice as highly expressive or poetic.

Obfuscated coding. Competitors are invited to write short programs that do anything they like while making the code for these programs intentionally hard to understand. Both levels are deeply engaged, with programmers having the option to pursue unusual machine function and to cloak the human meaning of their programs in clever ways. Although making programs intentionally hard to understand is not the only interesting way to code with regard to human meaning, it is an effort that resists the usual values of elegance, simplicity, and clarity. In many of the best obfuscated programs, the visual appearance of the code relates interestingly to its fuction — in some cases, the code itself is used as data by the running program — and obfuscation is achieved both my making the program’s workings byzantine and by choosing very difficult-to-understand means of implementing these workings. Obfuscated coding is one type of programming that is a writing practice and is also highly creative.