I came across the macro with-eval-after-load
when trying to install persp-mode
from here. But I am unable to find the macro inside Emacs and/or on Google. Where is it defined? Is it part of standard Emacs Lisp?
Asked
Active
Viewed 1.2k times
41

itsjeyd
- 5,070
- 2
- 30
- 49

Talespin_Kit
- 20,830
- 29
- 89
- 135
1 Answers
64
From etc/NEWS
:
* Lisp Changes in Emacs 24.4
...
** New macro `with-eval-after-load'.
This is like the old `eval-after-load', but better behaved.
Emacs 24.4 was released on 20th October 2014.
eval-after-load
is considered ill-behaved because it is a function, not a macro, and thus requires the code inside it to be quoted, which means that it cannot be byte-compiled. It also accepts only one form, so if you have more than one, you need to use progn
. For example:
(eval-after-load "foo"
'(progn
(setq foo 42)
(setq bar 17)))
The equivalent version with with-eval-after-load
would be:
(with-eval-after-load "foo"
(setq foo 42)
(setq bar 17))
As noted by Clément in a comment, one disadvantage of with-eval-after-load
is that you cannot rely on macros defined in the module in question, while with eval-after-load
you can be sure that such macros are defined and available to use. This was discussed on emacs-devel.

legoscia
- 39,593
- 22
- 116
- 167
-
2*FWIW:* If that's all that is meant by "better behaved" then I'd say that that is pretty much false advertising. I sincerely hope there is a better reason than what is given in the `NEWS` for bothering to add this macro to Emacs. – Drew Feb 19 '14 at 15:12
-
8@Drew `with-eval-after-load` arranges for the body to be byte-compiled, whereas `eval-after-load` does not. That was the main reason for its addition, iirc. – Feb 19 '14 at 17:57
-
@lunaryorn: Ah, yes, that makes sense. (Though often the body is not something that benefits much from compiling. And byte-compiling does not necessarily make for "better behavior".) Another important difference is that (according to the paltry doc) the macro apparently evaluates `BODY` "***each time*** `LIBRARY` is loaded". (*Not* doing that is one of the aims of `eval-after-load`.) – Drew Feb 19 '14 at 18:50
-
3@lunaryorn: I was wrong that evaluating `BODY` each time is a difference. See Emacs [bug #16810](http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16810). – Drew Feb 19 '14 at 19:38
-
5On the other hand, the semantics of with-eval-after-load are subtly different: you can't (reliably) call a macro defined in package `foo` in a `with-eval-after-load 'foo` block. https://lists.gnu.org/archive/html/emacs-devel/2018-02/msg00714.html – Clément Feb 26 '18 at 05:35
-
@Clément thank you for prying that info from Stefan. I would never have figured out how or why this was happening. – hraban Sep 03 '21 at 00:48