Indenting Common Lisp

Introduction

The term indentation refers to the amount of white space at the beginning of lines of code. But here we use the term in a slightly more general way. We use it to mean all rules for the physical layout of a program, such as when to use newlines, how many semicolons to use in comments, etc. It is very important to indent Common Lisp programs correctly; much more important than to indent C or Java programs. The reason is that experienced Lisp programmers read and understand Lisp code based on indentation as opposed to some other way, such as counting parentheses.

But the programmer cannot be trusted to indent correctly. Therefore, it is equally important that the text editor (usually Emacs) be taught how to indent properly.

Notice that indentation rules are not a matter of personal taste, but a matter of shared culture. The rules for indenting Lisp programs have evolved over a number of years as a kind of standard in the Lisp community. It is not up to the individual student to invent his or her own indentation rules. The argument is one of maintainability. A program is usually maintained by people other than those who wrote it. Standardized rules for indentation play an important rôle in facilitating maintenance, in particular of Lisp programs.

In this section, we give the most common rules for indenting Lisp programs, together with the Emacs expressions that accomplish them.

General rules

Top-level functions

All top-level function definitions start in column 1. This is important, since Emacs uses that information to search for the beginning of function definitions.

Closing parentheses

Closing parentheses are never preceded by newlines. Thus, do not write like this:
  ;;; bad
  (defun f (x)
    (when (< (g x) 3)
       (h x 2)
    )
  )
Instead write like this:
  ;;; good
  (defun f (x)
    (when (< (g x) 3)
       (h x 2)))
The first method may seem better to some people, since it is easier to match parentheses, but as we have already mentioned, readers of Lisp programs do not match parentheses, but use indentation.

The first method also requires more lines for the same code. In general, it is good to keep the number of lines down, so that more code will fit on a page or a screen; subject to the indentation rules, of course.

Amount of indentation

Unless more specific rules state otherwise, the level of indentation should be relatively small. We use two characters. Thus, do not write like this:
  ;;; bad
  (defun f (x)
      (when (< (g x) 3)
          (h x 2)))
Instead write like this:
  ;;; good
  (defun f (x)
    (when (< (g x) 3)
      (h x 2)))
The reason for the modest indentation is to lower the probability of lines sticking too far out to the right, which in turn would require more newlines and thus more lines in the program. Again, we try to keep the number of lines down.

Comments

Number of semicolons

Comments in Common Lisp start with a semicolon and end at the end of a line. Over the years, a style has developed that uses between one and four semicolons, according to the scope of the comments.

A single semicolon is used for a comment concerning a single line of code, and located on the same line as the code, for instance:

  (if (< (g x) 2)     ; is it sufficiently small?
      (top-level x)   ; if so, abandon everything
      (h y))          ; otherwise try again
Two semicolons are used for a comment that cover several lines of code. The comment line is lined up the the code lines, and precedes them, like this:
  (when (< (g x) 2)
    ;; reinitialize and abandon everything
    (setf *level-number* 0)
    (top-level x))
Three semicolons are used for comments that explain a function. Such comments always start in column 1, like this:
  ;;; Compute the amount of space between symbols
  ;;; as a list of floating point values.
  (defun compute-spaces (symbols)
    (mapcar #'compute-single-space symbols (cdr symbols)))

Content of comments

As usual, we try to be brief, without losing the information contents. For comments to function definitions, a good idea is to use the imperative form of the verb. This way you can avoid redundant expressions such as ``this function''. Do not write like this:
  ;;; This function computes the space between symbols
  ;;; as a list of floating point values
  (defun compute-spaces (symbols)
    (mapcar #'compute-single-space symbols (cdr symbols)))
Instead, write like this:
  ;;; Compute the amount of space between symbols
  ;;; as a list of floating point values.
  (defun compute-spaces (symbols)
    (mapcar #'compute-single-space symbols (cdr symbols)))

Indenting special forms

Each special form has its own indentation rule. Here, we give a list of the most common ones.

Indenting the if special form

The if special form in Common Lisp takes exactly three subexpressions. The subexpressions should be lined up, like this:
  (if (= (f x) 4)
      (top-level x)
      (g x))
This indentation is accomplished by the following Emacs expression that you can put in your .emacs file:
 (put 'if 'lisp-indent-function nil)

Indenting the when and unless special forms

These forms both take an arbitrary number of subexpressions, the first of which is distinguished as the test. We write the test on the same line as the name of the special form, and all the other forms on separate lines, indented by two positions, like this:
  (when (= (f x) 4)
    (setf *level-number* 0)
    (unless *do-not-reinitialize*
      (reinitialize-global-information x)
      (reinitialize-local-information))
    (top-level x))
This indentation is accomplished by the following Emacs expression that you can put in your .emacs file:
  (put 'when 'lisp-indent-function 1)
  (put 'unless 'lisp-indent-function 1)

Indenting the let and let* special forms

These forms both take an arbitrary number of subforms. The first is a list of variable initializations, and the rest are the body of the special form. The variable initializations start on the same line as the name of the special form, and the initializations is lined up. The body is indented by two characters like this:
  (let* ((symbols (mapcar #'compute-symbol l))
         (spaces (mapcar #'compute-space symbols (cdr symbols))))
    (when (verify-spacing symbols spaces)
      (make-spacing permanent spaces)))
This indentation is accomplished by default in emacs.

Indenting the do and do* special forms

These forms both take an arbitrary number of subforms, the first two of which are distinguished. The first one contains the loop variables and the second is a loop termination form. The rest are the body of the special form. Here is an example:
  (do ((i 1 (1+ i))
       (j (length l) (/ j 2)))
      ((= j 0) i)
    (iterate i j)
    (when (= (f x) 4)
      (setf *level-number* 0)
      (top-level x)))
This indentation is accomplished by the following Emacs expression that you can put in your .emacs file:
  (put 'do 'lisp-indent-function 2)
  (put 'do* 'lisp-indent-function 2)