all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Nicolas Richard <theonewiththeevillook@yahoo.fr>
To: Alexander Shukaev <haroogan@gmail.com>
Cc: John Mastro <john.b.mastro@gmail.com>,
	help-gnu-emacs <help-gnu-emacs@gnu.org>
Subject: Re: Macro Expansion Inconsistency
Date: Wed, 17 Dec 2014 11:04:58 +0100	[thread overview]
Message-ID: <87r3vyegmt.fsf@yahoo.fr> (raw)
In-Reply-To: <CAKu-7Wyak5UNk6Yb8c3hObaqkySxHJeK72P0S6a8QJiK9OT0eg@mail.gmail.com> (Alexander Shukaev's message of "Wed, 17 Dec 2014 03:19:14 +0100")

Alexander Shukaev <haroogan@gmail.com> writes:

> I currently have the following macro baked:
>
> (defmacro bm-define-flag
>     (name index character foreground)
>   (let* ((symbol           (intern (format "bm-%s-flag"
>                                            (symbol-name name))))
>          (character-symbol (intern (format "%s-character"
>                                            (symbol-name symbol)))))
>     (put symbol 'index     index)
>     (put symbol 'character character-symbol)
>     (eval `(defcustom ,character-symbol
>              ,character
>              "Character for flag."
>              :tag "BM Flag Character"
>              :group 'buffer-manager
>              :type 'character))
>     (eval `(defface ,symbol
>              `((t :foreground ,foreground
>                   :weight     bold))
>              "Face for flag."
>              :tag "BM Flag Face"
>              :group 'buffer-manager-faces))))
> [...]
> causes the error: (void-variable bm-xxx-flag) in `eval'
> [...]
> How to overcome it?

Quick'n'very-dirty : add nil or t (or anything that can be evaluated
twice safely) at the end of your macro definition.

> Do you have any further recommendations on this macro?

It's awful :) But don't worry : it's easy to write awful things, and
it's good that you post about it here.

In your case I'd point out these problems :
(i) it uses explicit eval for no good reason
(ii) it doesn't return code (that's the error you see)
(iii) it relies on dynamical binding (because of ',foreground' in a
second layer of quasi-quoting, which is only evalled by the explicit
eval.).

I think this works (lightly tested) :

(defmacro bm-define-flag (name index character foreground)
  (let* ((symbol           (intern (format "bm-%s-flag"
                                           (symbol-name name))))
         (character-symbol (intern (format "%s-character"
                                           (symbol-name symbol)))))
    (put symbol 'index     index)
    (put symbol 'character character-symbol)
    `(progn ;; this is the code we're going to return after expansion.
            ;; Emacs will eval the whole progn form.
       (defcustom ,character-symbol
         ,character
         "Character for flag."
         :tag "BM Flag Character"
         :group 'buffer-manager
         :type 'character)
       (defface ,symbol
         '((t :foreground ,foreground ;; the comma can be used,
                                      ;; even after normal quoting
               :weight     bold))
         "Face for flag."
         :tag "BM Flag Face"
         :group 'buffer-manager-faces))))


If you'd like to read more about macros, I wrote about them at 
http://lists.gnu.org/archive/html/help-gnu-emacs/2014-09/msg00473.html
(there's a typo in the first paragraph, apply
`sed s/evaluation time/expansion time/' please)

HTH,

-- 
Nicolas Richard



  reply	other threads:[~2014-12-17 10:04 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <mailman.16228.1418763453.1147.help-gnu-emacs@gnu.org>
2014-12-16 21:10 ` Macro Expansion Inconsistency Joost Kremers
2014-12-16 21:25   ` Alexander Shukaev
2014-12-16 21:46     ` John Mastro
2014-12-16 22:58       ` Alexander Shukaev
2014-12-16 23:14         ` Alexander Shukaev
2014-12-17  2:19           ` Alexander Shukaev
2014-12-17 10:04             ` Nicolas Richard [this message]
2014-12-17 14:03               ` Alexander Shukaev
2014-12-17 14:20                 ` Stefan Monnier
2014-12-17 14:34                   ` Alexander Shukaev
2014-12-17 14:21                 ` Nicolas Richard
2014-12-17 14:52                   ` Alexander Shukaev
2014-12-17 14:58                     ` Nicolas Richard
2014-12-17 15:14                       ` Alexander Shukaev
     [not found]               ` <mailman.16290.1418825041.1147.help-gnu-emacs@gnu.org>
2014-12-17 15:53                 ` Barry Margolin
2014-12-17 16:01                   ` Alexander Shukaev
     [not found]           ` <mailman.16262.1418782759.1147.help-gnu-emacs@gnu.org>
2014-12-17  3:03             ` Rusi
2014-12-17  9:21               ` Nicolas Richard
2014-12-16 23:20         ` John Mastro
     [not found]           ` <CAKu-7WzgoHH=zM_jxeVGMwzAne88nAoCUsLKQv9zUYo_amsjNg@mail.gmail.com>
2014-12-17  3:34             ` John Mastro
2014-12-17  3:41               ` John Mastro
2014-12-16 23:30   ` Stefan Monnier
2014-12-16 20:57 Alexander Shukaev

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87r3vyegmt.fsf@yahoo.fr \
    --to=theonewiththeevillook@yahoo.fr \
    --cc=haroogan@gmail.com \
    --cc=help-gnu-emacs@gnu.org \
    --cc=john.b.mastro@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.