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)))
  • 1
    eval-after-load is a poorly designed function which you shouldn't take as example for anything :) – lunaryorn Feb 6 '16 at 18:23
  • 2
    Section 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 6 '16 at 18:25
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.)

  • You could mention the macro with-eval-after-load, which was added in a fairly recent Emacs version. It is mostly equivalent to your run-after-load. – Constantine Feb 6 '16 at 18:54
  • @Constantine Good catch! Done. Thanks. – Harald Hanche-Olsen Feb 6 '16 at 19:02
  • 2
    It's new in 24.4, specifically (check NEWS: <f1> n). – npostavs Feb 6 '16 at 19:11
  • Whoops, I had forgotten a quote! After all, eval-after-load does evaluate its argument, right? Which is what was causing trouble for the OP. In any case, hopefully most users will have emacs 24.4 and just go with with-eval-after-load` instead. – Harald Hanche-Olsen Feb 8 '16 at 11:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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