emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Macro expansion: Why doesn't the invoked macro see (let (variables))


From: Stefan Monnier
Subject: Re: Macro expansion: Why doesn't the invoked macro see (let (variables))from the invoking one?
Date: Wed, 08 Feb 2012 14:52:45 -0500
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.92 (gnu/linux)

> (defmacro run-hooks-here ()
>    (setq hooks-called t)        <================= flag variable
>   `(run-hooks ',hook (if ,mode ',hook-on ',hook-off)))

> (defmacro define-minor-mode (....)
> ....
>   (let (... hooks-run)
> ....
>     ,@body                  <================= expand invoker's forms

This comment is wrong: ",@body" just plugs in the `body' without
macro-expanding it.

>                             <====== There may be (run-hooks-here) here.
>     ,@(unless hooks-run `((run-hooks-here))) <========= test flag

You can do that, but you then need to make sure the `body' gets
macro-expanded while the `let' is live, i.e. during the expansion of the
call to `define-minor-mode'.
You can do it with something like

   (defmacro define-minor-mode (....)
   ....
     (let (... hooks-run)
   ....
       ,@(macroexpand-all body) <================= expand invoker's forms
                               <====== There may be (run-hooks-here) here.
       ,@(unless hooks-run `((run-hooks-here))) <========= test flag


But note that this counts as ugly.  We use such tricks in cl-macs.el to
figure out whether `body' uses `return-from' within a `block' (in order
to optimize away the `catch' that's otherwise needed), but it's ugly,
inefficient, and brittle.
An :after-hook (or :late-code or some other name you prefer) is much
better in this regard.


        Stefan



reply via email to

[Prev in Thread] Current Thread [Next in Thread]