all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: pjb@informatimago.com (Pascal J. Bourguignon)
To: help-gnu-emacs@gnu.org
Subject: Re: Need some education on defmacro define-toggle
Date: Tue, 29 Dec 2009 01:37:08 +0100	[thread overview]
Message-ID: <871viezkcr.fsf@hubble.informatimago.com> (raw)
In-Reply-To: mailman.358.1262037566.18930.help-gnu-emacs@gnu.org

Lennart Borgman <lennart.borgman@gmail.com> writes:

> On Mon, Dec 28, 2009 at 10:33 PM, Pascal J. Bourguignon
> <pjb@informatimago.com> wrote:
>> Lennart Borgman <lennart.borgman@gmail.com> writes:
>>
>>> On Mon, Dec 28, 2009 at 6:16 AM, Lennart Borgman
>>> <lennart.borgman@gmail.com> wrote:
>>>> I just got into some trouble because of a badly written macro I
>>>> believe. After the long discussions about defmacro here I wonder if
>>>> anyone wants to help me out. How should I write the defmacro below?
>>>
>>>
>>> I resorted to self education (which is not too bad). However I still
>>> got problems - just on a more complicated level. The macro now looks
>>> like this:
>>>
>>> (defmacro define-toggle (symbol value doc &rest args)
>>>   "Declare SYMBOL as a customizable variable with a toggle function."
>>>   (declare   (doc-string 3)   (debug t))
>>>   (let* ((SYMBOL-toggle (intern (concat (symbol-name symbol) "-toggle")))
>>>          (SYMBOL-name (symbol-name symbol))
>>>          (var-doc doc)
>>>          (fun-doc (concat "Toggles the \(boolean) value of `" SYMBOL-name
>>>                           "'.\nFor how to set it permanently see this
>>> variable.\n")))
>>>     (let ((var (append `(defcustom ,symbol ,value ,var-doc)
>>>                 args
>>>                 nil))
>>>           (fun `(defun ,SYMBOL-toggle ()
>>>                    ,fun-doc
>>>                    (interactive)
>>>                    (customize-set-variable (quote ,symbol) (not ,symbol)))))
>>>       `(list 'progn ,var ,fun))))
>>>
>>> This seems to work, but if the call to define-toggle already has been
>>> done then loading a file with this define-toggle gives trouble:
>>>
>>> Debugger entered--Lisp error: (void-variable rngalt-display-validation-header-toggle)
>>>   (progn rngalt-display-validation-header rngalt-display-validation-header-toggle)
>>>   (define-toggle rngalt-display-validation-header t "Display XML validation headers at the top of buffer when t.\nThe validation header is only displayed in buffers where the main\nmajor mode is derivd from `nxml-mode'." :set (lambda (sym val) (set-default sym val) (rngalt-update-validation-header-overlay-everywhere)) :group (quote relax-ng) :group (quote nxhtml))
>>>
>>> ...
>>>
>>> There is obviously something I got wrong in the evaluation order since
>>> now, in this situation, the macro now tries to evaluate
>>>
>>>   (progn rngalt-display-validation-header rngalt-display-validation-header-toggle)
>>>
>>> I expected it to redefine the defcustom and the defun instead.
>>> Can someone please try to explain what is going on?
>>
>> There must be an eval somewhere that tries to evaluate one time too many.
>
>
> Hm, yes, but it is not mine...
>
> As you can see from the backtrace there is some eval-buffer in the stack.
>
>
>
>> That said, why doesn't your macro just return
>>
>>   `(progn ,var ,fun)
>>
>> instead of returning a list form that evaluates to something such as
>>
>>   (progn rngalt-display-validation-header rngalt-display-validation-header-toggle)
>>
>> that needs to be evaluated (and of course fails since you didn't
>> define these symbols as variables)?
>
>
> It fails sometimes, but not always. It looks like it has something to
> do with those eval above, but I do not understand how. If I just do
> eval-buffer it works as I expect it to.
>
> I have done some small changes and at the moment it seems to work, but
> I have no idea why... There is clearly something in the order of
> evaluation that beats me. If I just print out the values of fun and
> var before comuting the result to return they look as I expect them
> to, ie they are lists. But then in the progn list they are converted
> to symbols, in some step.

Of course, when you evaluate `(list 'progn ,defcustom-form ,defun-form)
the defcustom and the defun are evaluated, and they return their name argument.

That's why I advise you to write instead:

     `(progn ,defcustom-form ,defun-form)


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/


  parent reply	other threads:[~2009-12-29  0:37 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-12-28  5:16 Need some education on defmacro define-toggle Lennart Borgman
2009-12-28 19:28 ` Lennart Borgman
     [not found] ` <mailman.352.1262028532.18930.help-gnu-emacs@gnu.org>
2009-12-28 21:33   ` Pascal J. Bourguignon
2009-12-28 21:58     ` Lennart Borgman
     [not found]     ` <mailman.358.1262037566.18930.help-gnu-emacs@gnu.org>
2009-12-29  0:37       ` Pascal J. Bourguignon [this message]
2009-12-29  0:49         ` Lennart Borgman

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=871viezkcr.fsf@hubble.informatimago.com \
    --to=pjb@informatimago.com \
    --cc=help-gnu-emacs@gnu.org \
    /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.