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/
next prev 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.