2

I'm editing a Common lisp (not elisp) source file; bottom right says (Lisp adoc [COMMON-LISP-USER sbcl]). I'm using slime, so I'm pretty sure that's what the adoc means.

I have the following in a common lisp source file: a macro from "ANSI common lisp" by graham, along with a usage of that macro:

(defmacro while (test &rest body)
  `(do ()
       ((not ,test))
     ,@body))

(defun bar ()
  (let ((x 0))
    (while (< x 10)
           (princ x)
           (incf x)))

I don't like the indentation in the definition of bar, I would like it to be

(defun bar ()
  (let ((x 0))
    (while (< x 10)
      (princ x)
      (incf x)))

Looking at the emacs manual, specifically this page:

You can override the standard pattern in various ways for individual functions, according to the lisp-indent-function property of the function name. This is normally done for macro definitions, using the declare construct. See Defining Macros in The Emacs Lisp Reference Manual.

Following that link, I tried adding (declare (indent defun)) right below my defmacro while line. However after adding that and C-c C-c to re-execute the macro into my slime-repl sbcl window, the indentation in my source code window is not affected, and defun bar still has the original indentation for while.

Additionally, in the source code, the indent defun part is highlighted and an tooltip says "unrecognized declaration".

What am I doing wrong here? Is it because the declare thing is for elisp only, and I'm editing common lisp code?

Note that the undesired indentation is present both in my source code and in the REPL window, e.g. if I try to directly use my while macro from the SLIME repl.

Additionally, I looked in the Slime manual pdf which says

3.14 Semantic indentation SLIME automatically discovers how to indent the macros in your Lisp system. To do this the Lisp side scans all the macros in the system and reports to Emacs all the ones with &body arguments. Emacs then indents these specially, putting the first arguments four spaces in and the “body” arguments just two spaces, as usual.

I wonder why it's not working? Is it because I have &rest body instead of &body?

Using emacs 29.2 on fedora 39.

1 Answer 1

2

It's because I used &rest body instead of &body body. Once I used the latter, the indentation automatically worked fine in both places, no declare needed.

Probably &body was not a thing when Paul graham wrote ANSI common lisp in the 90s?

source code:

(defmacro while (test &body body)
  `(do ()
       ((not ,test))
     ,@body))

(defun bar ()
  (let ((x 0))
    (while (< x 10)
      (princ x)
      (incf x))))

REPL:

CL-USER> (let ((x 0))
           (while (< x 10)
             (princ x)
             (incf x)))
0123456789
NIL
CL-USER> 

From this Google group thread it seems &body existed as early as 2000:

Apr 23, 2000, 3:00:00 AM ... I am new to Lisp and am wondering what is the difference between using &rest and &body in a macro definition. They appear to do the same thing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.