Credits: Google Common Lisp Style Guide, Emacs 21.2 Manual, Strandh’s Tutorial on Indentation, Rainer Joswig, ACow_Adonis, following Reddit users: defunkydrummer, lispm, KaranasToll, kazkylheku, theangreymacsshibe, xach, zulu-inoe

Lisp is infamous for its reliance on parentheses ( ) to delimit code and is notorious for being difficult to read because of this. As many experienced lisp programmers have pointed out, and as this article will hopefully show, properly indented code makes reading lisp much easier and the parentheses disappear into the background.

In this article, we will discuss some basic concepts for formatting Lisp code and I will share with you my personal notes, as a professional designer of presentations and reports. I hope you find it useful and that it makes it easier for you to read, write and enjoy lisp code.

1: Executive Summary

Lisp code should be formatted according to the following guidelines.

Indenting

Indent your code the way a properly configured GNU Emacs does. In practise, this means relying on a lisp editor (such as Emacs) that indents code automatically.

  • Function ArgumentsAligned with the first argument; if the first argument is on its own line, it is aligned with the function name
  • Body of FormsIndented two spaces
  • Distinguished (“special”) ArgumentsIndented four spaces

Examples

;; Align arguments to a function with the first argument:
(my-function arg-one
             arg-two
             arg-three)
;; Or under the function name:
(my-function
 arg-one
 arg-two
 arg-three)
;; Body should be nested two spaces:
(when something
  (do-this)
  (and-this)
  (and-also-this))
;; Distinguished forms should be nested four spaces:
(with-slots (a b)
    distinguished-form
  (print a)
  (print b))

Line Spacing / Newlines

When an lisp form does not fit on one line, consider inserting newlines between the arguments so that each one is on a separate line. However, do not insert newlines in a way that makes it hard to tell how many arguments the function takes or where an argument form starts and ends.

;; Bad:
(do-something first-argument second-argument (lambda (x)
    (frob x)) fourth-argument last-argument)

;; Good:
(do-something first-argument
              second-argument
              #'(lambda (x) (frob x))
              fourth-argument
              last-argument)

Spacing of Parentheses

Always space elements like this: (+ (1 2) 3) and never like this (+(1 2)3) or (+ ( 1 2 ) 3).

Do not put ending parentheses on newlines

Always put ending parentheses on the last line, and not seperately on a newline. Lisp programmers read code by indentation and not by parentheses so we do not need to allocate extra lines for closing parentheses.

;; Good:
(defun our-equal (x y)
  (or (eql x y)
      (and (consp x)
           (consp y)
           (our-equal (car x) (car y))
           (our-equal (cdr x) (cdr y)))))
;; Bad:
(defun our-equal (x y)
  (or (eql x y)
      (and (consp x)
           (consp y)
           (our-equal (car x) (car y))
           (our-equal (cdr x) (cdr y))
      )
  )
)

Vertical lines between top-line forms

We should keep one blank line between top-level forms, unless they relate to definitions that are related to each other, e.g.:

;; Good:

(defun function-one
  ...)
(defun function-two 
  ...)
;; Bad:
(defun function-one
  ...)
(defun function-two 
  ...)
;; This is okay:
(defvar font "Arial")
(defvar bg-color "Black")
(defvar text-color "White")
(defvar font-size "12pt")

#code #programming #programming-languages #lisp

Formatting Lisp
4.10 GEEK