Lisp Coding Standards v1.0

Over the years I've read many many Lisp programs.   Some were written by others and some  were written by me months or years earlier (so to me it was like looking at a program I'd never seen before).  I've noticed what makes it hard to read and understand a program and what makes it  a pleasure to read.  I wrote this document as a reminder to myself of the rules I must follow to write readable Lisp code.    I intend to keep extending the set of rules as time permits.

This document describes a Lisp coding standard designed primarily to increase code readability.   Files that follow this standard may be marked with the url   

Note well: The document contains the opinions of its author (John Foderaro) only and may or may not reflect the opinions of anyone else at Franz Inc and definitely do not denote an official policy of Franz Inc which has graciously permitted the author  the use of its web server to store this page.

It has been noted that a program is written only once yet read many times.    Thus program readability has to be a primary concern of the programmer. It's likely that the person reading your code will have far less knowledge of how you've solved the problem at hand than you have at the time you wrote the code.    Thus you must strive to make your code readable by someone with little knowledge of the code.

I've found that the key to readability in Lisp functions is an obvious structure or framework to the code.   With a glance you should be able to see where objects are bound, iteration is done and most importantly where conditional branching is done.   The conditionals are the most important since this is where the program is deciding what to do next.   Bugs often occur when the conditional can't handle all possible cases.   If you're planning on extending the function you need a clear idea of the possible inputs it's willing to accept and what you can assert to be true for each branch of the conditional. 

Thus to me the most important expression in one's code is the conditional expression.    These must be expressed as clearly as possible.   Common Lisp offers four conditional expressions: cond, if, when and unless.   Common Lisp also provides a powerful macro facility that permits you to extend the language.   I chose to use the macro facility to extend the language to create a conditional expression that I felt gave me the readability that the conditional expression should have.  This macro is called if*.   The source code for if* can be found here and the documentation here.

The if* macro along with proper indenting support in the editor makes glaringly apparent the structure of conditionals.  They stand out like a sore thumb.   Furthermore one can easily extend an if* conditional adding expressions to the then or else clauses or adding more predicates with elseif.    Thus once you've laid out the conditional you can easily extend it without changing the expression itself (contrast that to having to go from when to if to cond as you grow the conditional using the built-in Common Lisp conditional forms).

Now that we've introduced if* here are the coding rules;

  1. Use if* in place of if, when, unless and cond.    Make the conditionals in your code stick out.  Avoid situations where adjacent expressions are not evaluated sequentially since that's at odds with how evaluation is done for most expressions in the language.  With (if a b c) b may not be evaluated after a and c is never evaluated after b.  In this case you can see the if sitting off to the left but imagine a, b, and c to be large expressions so that the if* is out of your field of vision.  With if* this is not a problem (if* a then b else c).   In this case no matter how large a, b and c get there will always be keywords between them to make you realize as you read the code that sequential expression evaluation is not necessarily going to happen.
  2. Use do, dotimes and dolist for iteration in place of   the extended loop macro (the one using the keywords).   The structure of the code inside a loop is not apparent.   Thus a function with loop in it is opaque until you've read carefully through all the keywords used in the expression.
  3. Comment your code.   Avoid obvious comments as that will make it harder to find the meaningful comments.