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

Re: do-nothing macro generates nil nevertheless



In article <gat-260295131710@milo.jpl.nasa.gov>,
Erann Gat <gat@robotics.jpl.nasa.gov> wrote:
>In article <3iqno7$mab@news.internex.net>, yost@rclsgi.eng.ohio-state.edu
>(Dave Yost) wrote:
>
>>I've been implementing some debug macros that only
>generate code depending on what's in *features*.
>
>The proper way to do this is to use the #+ read macro, e.g.:
>
>(progn
>  3
>  #+debug(do-debugging-stuff))

My macros are more sophisticated than this.
I hope to post them soon.

 >> Consider this macro:
 >>
 >>   (defmacro mac1 () nil)
 >>
 >> Now consider this form:
 >>
 >>   (progn
 >>     3
 >>     (mac1))
 >>
 >> which returns nil.  (in MCL and CMU-CL)
 >> This seems to me to be a misfeature.
 >
 >No, this is doing the Right Thing.  The body of mac1 returns nil which
 >means that (progn 3 (mac1)) becomes (progn 3 nil) which should return nil.
 >
 >> A macro's job is to return a list to be compiled.
 >> If it returns nil, I would have thought that would mean
 >> that nothing should be compiled.  That would be useful.
 >
 >Not quite.  A macro returns a FORM to be compiled, not a list.  Nil
 >is a perfectly valid Common Lisp form, one that happens to evaluate
 >to itself.
 >
 >> If you need a macro to compile in the constant nil, you
 >> can have it return 'nil.
 >
 >In Common Lisp, nil, 'nil, () and '() are all the same thing.

You're telling me how it works, and I'm saying how I think it should work.
My point is that some functionality is not provided:
namely, the ability of a macro to expand into _nothing_.

>Another way to achieve the effect you want is to write a surrounding
>macro that removes all the nil forms, e.g.:
>
>(defmacro yost-progn (&body body)
>  `(progn ,@(remove nil (mapcar #'macroexpand body))
>
>but this is pretty hideous programming practice.  Your "implicit-progn"
>could be implemented analogously, by making a pass over the body and
>replacing every occurence of (form) (return-value-trasnparent ...) with
>(prog1 (form) ...).

This is a hack that doesn't address the missing functionality.

>>   (with-captured-return-values (var) &body body)
>
>Isn't this the same as LET?

No.  The var argument is bound to a list of the value(s) that
would be returned if this form were not present, and if no other
forms follow in the progn.