3

Recently I was trapped by void-variable error on eval-after-load.

That is not first time I forget to quote args like:

(eval-after-load 'sql
   '(progn
       ...))

because eval-after-load docs say:

(eval-after-load FILE FORM)

I wrongly expect that FORM is like BODY... for example in when:

(when COND BODY...)

What is the difference between FORM and BODY function call contract?

Why are there FORM when BODY is more convenient?

BODY only for macros and FORM only for functions?

Is (quote (progn ...)) usual way to make multi expression FORM?

UPDATE Seems my guess is right about BODY only for macros and FORM only for functions:

(defmacro with-eval-after-load (file &rest body)
  "Execute BODY after FILE is loaded.
FILE is normally a feature name, but it can also be a file name,
in case that file does not provide any feature."
  (declare (indent 1) (debug t))
  `(eval-after-load ,file (lambda () ,@body)))
Constantine
  • 9,072
  • 1
  • 34
  • 49
gavenkoa
  • 3,352
  • 19
  • 36
  • 1
    eval-after-load is a poorly designed function which you shouldn't take as example for anything :) –  Feb 06 '16 at 18:23
  • 2
    Section [Forms](https://www.gnu.org/software/emacs/manual/html_node/elisp/Forms.html#Forms) in the manual gives this definition: *a Lisp object that is intended to be evaluated is called a form (or an expression)*. Regarding bodies and macros: both function calls and macro calls may take a "list" (**not** in the Lisp sense) of forms, which is usually called a "body". You can recognize ones that can take several forms by the `&rest` keyword in the argument list. (I'm leaving this as a comment because I don't have the time to write a proper answer.) – Constantine Feb 06 '16 at 18:25

1 Answers1

3

There are two issues here.

On the one hand, when a function is called, the arguments are evaluated first. But when you evaluate a macro, the arguments are not evaluated. Instead, they are used to expand the macro into a form, which is subsequently evaluated.

On the other hand, a form is just a single lisp object that is going to be evaluated, while a body is a sequence of forms.

It is true that macro calls more commonly contain a body than a single form. This has less to do with their macro-ness than with what is more natural in each case, however.

The built-in function eval is something of a special case: It is a function, hence when you call it, its argument is evaluated. But then, it evaluates its (already evaluated) argument again. The purpose of this is so you can programmatically build a lisp form and then evaluate it. This is rarely needed in ordinarty programming, however – but it's a common beginner's error for new lispers to use eval needlessly.

And so at last we get to eval-after-load: I imagine it is a function primarily because its perceived relationship with plain eval. It might have been better to have it being a macro, but then the name should have been different so it's not so easily confused with the semantics of eval. Perhaps run-after-load? You can easily make one such yourself, perhaps even allowing it a body:

(defmacro run-after-load (file &rest body)
  `(eval-after-load ,file '(progn ,@body)))

Edit: There is in fact a macro with-eval-after-load in newer emacsen (since 24.4) which is almost identical to the above. (It wraps the body in a lambda instead of a progn.)

Harald Hanche-Olsen
  • 2,401
  • 12
  • 15