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

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

Re: Is it possible for a macro to expand to nothing?


From: Pascal J. Bourguignon
Subject: Re: Is it possible for a macro to expand to nothing?
Date: Tue, 24 Nov 2009 00:55:13 +0100
User-agent: Gnus/5.1008 (Gnus v5.10.8) Emacs/22.3 (darwin)

"Drew Adams" <drew.adams@oracle.com> writes:

>> > Sorry, but it works just fine. I do this all the time.
>> 
>> No, it doesn't:
>> (defmacro ifdef (expr &rest body)
>>    (and (eval expr) `(progn ,@body)))
>> (ifdef t ((setq bar 2)))
>> Debugger entered--Lisp error: (invalid-function (setq bar 2))
>
> You seem to be complaining about yourself. I never suggested using such a 
> macro.
>
> All I suggested was to use backquote with ,@ to splice in a list with the
> element that Alan conditionally wants in the macroexpansion. That's the way to
> add something or nothing to a list: put the something or nothing in a list, 
> then
> splice in that list.
>
> The list to be built here is a defun expression. It is then evaluated without
> problem.
>
>> I said that it was a bad idea to take the habit of giving
>> an invalid form to a macro to get an invalid form from it.
>
> Sorry, dunno what you're saying. There wasn't anything invalid in what I
> suggested.
>
> As far as I'm concerned, all that's really involved is writing a macro that
> expands to a list that contains or doesn't contain the element in question. 
> Any
> such list is a valid _list_.

This is the problem!  Macros shouldn't return a _list_, they should
return a _form_.  If you write a macro that returns a list, or you use
it so that it returns a list, that is not a valid form, then it is not
good style, even if you catch up.


> When the list resulting from macroexpansion is then EVALUATED, yes, of course
> its car must be a defined function, macro, `lambda', etc. (or the list must be
> nil). That is an entirely different matter. That is a consideration for _any_
> macro one writes.
>
> In Alan's case, the resulting list has `defun' as its car. It is a valid defun
> expression whose evaluation defines a function.

I don't mind titi, I  object to your use of ifdef in titi.  That ifdef
call returns a list that is not a valid form.  This is not good style.



> The only thing relevant here, AFAICT, is how to create the list Alan wants: a
> list that conditionally contains some element. Backquote plus ,@ is the 
> answer.

Yes, since you only want to create a list at that point, do not use a
macro, use a function.


>> Notice also my alternative solution uses macroexpand.   This is a clue
>> that if you want to go that way, you should use a function rather than
>> a macro:
>>    (defun %parenthesized-ifdef (expr forms)
>>       (if expr
>>           '()
>>           `((progn ,@forms))))
>>    (defmacro titi (fn)
>>       `(defun ,fn  ()
>>           (setq bar 1)
>>           ,@(%parenthesized-ifdef baz '((setq bar 2)))))
>> 
>> (macroexpand '(titi foo))
>> --> (defun foo nil (setq bar 1) (progn (setq bar 2)))
>
> Dunno why you do all that. 

Because it is a better style.  It avoids abusing the ifdef macro.


> (And there is no need to quote nil.)

There are again very good stylistic reasons to quote nil or ()
depending on the case.


> Again, all of that code boils down to just this (which is what I wrote 
> earlier):
>
> (defmacro titi (fn)
>   `(defun ,fn ()
>     (setq bar 1)
>     ,@(and baz '((setq bar 2)))))

I'm OK with this version (since it doesn't abuse the ifdef macro).


> I'm sure you know what you're talking about, and I know what I'm
> talking about ;-). The only real question is whether either of us
> has actually helped Alan at all.

Well, he has a lot of solutions to choose from now.  Indeed, his
situation may not be better :-)

-- 
__Pascal Bourguignon__


reply via email to

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