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.
;;; 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.
;;; 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.
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 againTwo 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)))
;;; 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)))
(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)
(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)
(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.
(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)