help-gnu-emacs
[Top][All Lists]
Advanced

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

Re: Eval keymapp in a macros


From: Michael Heerdegen
Subject: Re: Eval keymapp in a macros
Date: Wed, 04 Aug 2021 02:18:09 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux)

Arthur Miller <arthur.miller@live.com> writes:

> So I ended with the one I posted which works, but I wonder why, and I
> don't really like it. I think you are correct about the reason. That is
> what I think also, so that is why I used eval, because I need the keymap
> object itself to pass to define-key, at least so I think. Maybe I am
> wrong there?

You are right.  What you get in the expansion is similar to what happens
here:

(let ((entry '([f11] . emacs-lisp-mode-map)))
  (define-key global-map (car entry) (cdr entry)))

which will also not "work".  You never evaluate the bindings - else you
would need to quote your command names.

With other words: you currently specify command names and keymaps in the
same way (as a symbol) - but the expansion needs to treat them
differently, obviously, since `define-key' always interprets a symbol as
a command name.  That can't work.  Your `keymapp' fix is an emergency
solution but it's not perfect: that test happens at compile time.  If
the keymap is not defined at compile time your compiled code will be
inappropriate.

The only solution for this is to rewrite your macro so that keymap and
command names are specified differently _in the call_.

> (insert (pp (macroexpand-1 
> '(defmacro with-key-map (mapname &rest body)
>   `(dolist (def '(,@body))
>      (define-key ,mapname
>        (if (vectorp (car def)) (car def)
>        (read-kbd-macro (car def)))
>        (if (keymapp (cdr def))
>            (eval (cdr def))
>        (cdr def)))))
> )))

I suggested to expand calls of the macro, not its definition ;-)

Unless you wanted to search for bugs in the implementation of
`defmacro'... but let's assume for now that your issue is caused by the
implementation of `with-key-map', and not by `defmacro' ;-)


> > Note that nothing in BODY is ever evaluated (it's behind a quote).
>
> Stuff in dolist gets evaluated, because dolist itself is a macro.
> The real body of function which is all in do list gets expanded by
> dolist (or the real interested part by 'while' which seems to be a
> special form) and then evaled by dolist. So dolist will actually call
> define-key for me, and that is what seem to happend, because stuff gets
> defined after I call the macro. I hope I understand correctly what is
> going on there.

Yes, see my example above: the (quoted) list gets evaluated, but not its
members, so you pass a symbol to `define-key' (what works for command
names but not for keymap names).


> As a side note, this isn't really a macro that writes a function or
> another macro and returns it. I have it partly to save myself typing,
> and partly to skip overhead of macroexpansion when Emacs start. Byte
> compiler will expand it when init file is byte compiled.  Actually I
> wrote a program to write my init file which does expansion when it
> outputs code to init file but it is just another regression.

Compiling is a good idea.  It would warn you if you misspelled a command
name (your version doesn't support that btw).

That concrete idea is cool but not really suitable for daily use, as you
already have found out: macro expansions can take damage after printing
and re-reading.

Why do you think you need that?  Why is normal code + normal compiling
not sufficient?


Michael.




reply via email to

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