- Always put parenthesis after the previous expression on its line, never on a line by itself. If you have trouble reading code formatted in this way, ignore the parens (or make them disappear by regexp-replace or font lock) and look at indentation.
- Use long, descriptive variable names. It's +buffer-size+, not +BUFSIZ+ or similar. This immensely helps reading comprehension and generally alleviates the need to comment the code (see below). I can't bring myself to read uncommented code in languages that don't allow hyphens in variable names, while I can read people's Lisp just fine. It doesn't apply when abbreviations are widely known (e.g.retval, i). Also abbreviate extremely long symbol names, e.g. frobnicate-svuc might be preferred to frobnicate-slot-value-using-class if the code is expected to fit in 80 columns.
- Comment non-obvious stuff. For instance, once I wrote the following code:
(defmacro fn (&environment env &body body) (with-walker-configuration (:undefined-reference-handler nil) ;; .VARS is modified implicitly in macroexpansion of the form ;; package protects against leaking symbols (let* ((.vars nil) (macro-name (gensym)) (ret (macroexpand-all `(macrolet ((,macro-name () (car (push (gensym) .vars)))) (symbol-macrolet ((_ (,macro-name))) (progn . ,body))) env))) (declare (special .vars)) `(lambda ,(reverse .vars) ,ret))))and had to add the comment because it wasn't immediately obvious what this code does.