[Top][All Lists]

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

Re: Need some education on defmacro define-toggle

From: Pascal J. Bourguignon
Subject: Re: Need some education on defmacro define-toggle
Date: Tue, 29 Dec 2009 01:37:08 +0100
User-agent: Gnus/5.101 (Gnus v5.10.10) Emacs/22.3 (gnu/linux)

Lennart Borgman <address@hidden> writes:

> On Mon, Dec 28, 2009 at 10:33 PM, Pascal J. Bourguignon
> <address@hidden> wrote:
>> Lennart Borgman <address@hidden> writes:
>>> On Mon, Dec 28, 2009 at 6:16 AM, Lennart Borgman
>>> <address@hidden> 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__           

reply via email to

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