From: Edward Dodge
Subject: Macro Help:  1 macro => many sexp
Date: 
Message-ID: <m2myzn9cwp.fsf@noreply.com>
I have a simple macro that takes a parameter and generates some
code to produce the parameters for an enclosing function.  Here's an
example of how this macro is called:

(enclosingfunction (macro "parameter1")
                   (macro "parameter2")
                   (macro "parameter3"))

This didn't take much thought because each macro matches each
parameter.  But I would like this code to be even more readable!  So
rather than call the same macro three times, with different
parameters, why not call the macro once, with three parameters?

(enclosingfunction (macro "parameter1" "parameter2" "parameter3"))

The problem now is this: how to getthe macro to return multiple
parameters and splice them into the enclosing form?

As a Lisp newbie, I'm used to dealing with aggregate items as strings
or as lists, but enclosingfunction will obviously not like it if I
pass it this:

(enclosingfuncion '((expandedmacro1) (expandedmacro2)...

Assuming I have built the list of macro expansions, how do I tell Lisp
to remove the outer '() and splice the results into enclosingfunction?


-- 
Edward Dodge

From: Rob Warnock
Subject: Re: Macro Help:  1 macro => many sexp
Date: 
Message-ID: <c6ydnUJ2uNAnn8DbnZ2dnUVZ_hOdnZ2d@speakeasy.net>
Edward Dodge  <······@noreply.com> wrote:
+---------------
| ...why not call the macro once, with three parameters?
|    (enclosingfunction (macro "parameter1" "parameter2" "parameter3"))
| The problem now is this: how to getthe macro to return multiple
| parameters and splice them into the enclosing form?
+---------------

You can't do exactly that, since no form can reach "outside" itself.[1]
Instead, you would need your macro to take the "enclosingfunction"
as an argument [now no longer "enclosing" per se] along with the
additional parameters to be modified/passed, e.g.:

    (defmacro your-macro (function-name &rest forms)
      `(,function-name ,@(mapcar #'your-transformer-function forms)))

Where YOUR-TRANSFORMER-FUNCTION is some ordinary function
of one s-expr, argument that returns one s-expr.

For example:

    > (defmacro funcall-with-incremented-args (function-name &rest forms)
	(flet ((transformer (x) `(1+ ,x)))
          `(,function-name ,@(mapcar #'transformer forms))))

    FUNCALL-WITH-INCREMENTED-ARGS
    > (* 2 3 4)

    24
    > (funcall-with-incremented-args * 2 3 4)

    60
    > (macroexpand '(funcall-with-incremented-args * 2 3 4))

    (* (1+ 2) (1+ 3) (1+ 4))
    T
    > 



-Rob

[1] Except perhaps by emitting references to free variables,
    usually a dangerous practice, but that's another story...

    Or by playing games with the macro &ENVIRONMENT, and
    that's a *whole* 'nother story!!

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Kent M Pitman
Subject: Re: Macro Help:  1 macro => many sexp
Date: 
Message-ID: <uwsyr7wos.fsf@nhplace.com>
Edward Dodge <······@noreply.com> writes:

> I have a simple macro that takes a parameter and generates some
> code to produce the parameters for an enclosing function.  Here's an
> example of how this macro is called:
> 
> (enclosingfunction (macro "parameter1")
>                    (macro "parameter2")
>                    (macro "parameter3"))
> 
> This didn't take much thought because each macro matches each
> parameter.  But I would like this code to be even more readable!  So
> rather than call the same macro three times, with different
> parameters, why not call the macro once, with three parameters?
> 
> (enclosingfunction (macro "parameter1" "parameter2" "parameter3"))
> 
> The problem now is this: how to getthe macro to return multiple
> parameters and splice them into the enclosing form?

I do this sometimes, but I usually write it as:

(macro (enclosing-function "parameter1" "parameter2" "parameter3"))

Generally a macro has no access to the enclosing form, unless some macro
farther out has conspired to arrange access (and usually that's so hairy
to do that it's not done even then).

This is the place where if the answer isn't "ok, I'll do that" then one
has to ask "What are you really trying to do?" so they can see why 
the obvious suggestion is not reasonable.

If you're just trying to stretch the Lisp macro system, you're at the
edge right there--it's a deliberate part of the design that you don't
have access to the rest of the state.

> As a Lisp newbie, I'm used to dealing with aggregate items as strings
> or as lists, but enclosingfunction will obviously not like it if I
> pass it this:
> 
> (enclosingfuncion '((expandedmacro1) (expandedmacro2)...
 
Right.  Well, the other thing you can do, of course, is to write a
readmacro.  It wouldn't fix your problem of coalescing macros but it
would allow you to more concisely call your macro three times.

MACLISP [a dialect that came before Common Lisp (and before the macintosh
computer, incidentally)] used to have a thing called a splicing macro 
which allowed a single readmacro to return several values as a list, 
where the reader would splice them into the containing stream.
The ; comment syntax was implemented by a splicing macro that 
called MACLISP's READLINE function to discard the rest of the line 
and then returned no forms ... and I *think* you might have been
able to have a splicing readmacro that returned several forms 
[in the annoying way that SGML entity references can do].  But unless
I've forgotten (it's been a while since I did any writing of readmacros
since I have a few I like and mostly don't muck with them a lot),
Common Lisp has no analogous feature.  It's probably just as well.

> Assuming I have built the list of macro expansions, how do I tell Lisp
> to remove the outer '() and splice the results into enclosingfunction?

Mostly, you don't.
From: Vassil Nikolov
Subject: Re: Macro Help:  1 macro => many sexp
Date: 
Message-ID: <kay7j57mcd.fsf@localhost.localdomain>
On 30 May 2007 00:38:27 -0400, Kent M Pitman <······@nhplace.com> said:
| ...
| MACLISP [a dialect that came before Common Lisp (and before the macintosh
| computer, incidentally)] used to have a thing called a splicing macro 
| which allowed a single readmacro to return several values as a list, 
| where the reader would splice them into the containing stream.
| The ; comment syntax was implemented by a splicing macro that 
| called MACLISP's READLINE function to discard the rest of the line 
| and then returned no forms ... and I *think* you might have been
| able to have a splicing readmacro that returned several forms 
| [in the annoying way that SGML entity references can do].  But unless
| I've forgotten (it's been a while since I did any writing of readmacros
| since I have a few I like and mostly don't muck with them a lot),
| Common Lisp has no analogous feature.  It's probably just as well.

  For completeness and historical reference, here is a relevant
  footnote, quoting from the compatibility note at the end of
  22.1.5. The Readtable, in the context of emphasizing Common Lisp's
  reader design as an attempt at simplicity:

    Splicing macros have been eliminated; a recent informal poll
    indicates that no one uses them to produce other than zero or one
    value.

  Steele, _Common Lisp: the Language_, p. 364.

  ---Vassil.


-- 
The truly good code is the obviously correct code.
From: Pillsy
Subject: Re: Macro Help: 1 macro => many sexp
Date: 
Message-ID: <1180517653.032620.138060@q69g2000hsb.googlegroups.com>
On May 30, 12:02 am, Edward Dodge <······@noreply.com> wrote:
[...]
> As a Lisp newbie, I'm used to dealing with aggregate items as strings
> or as lists, but enclosingfunction will obviously not like it if I
> pass it this:

> (enclosingfuncion '((expandedmacro1) (expandedmacro2)...

> Assuming I have built the list of macro expansions, how do I tell Lisp
> to remove the outer '() and splice the results into enclosingfunction?

I don't know how to tell Lisp how to do exactly that. However, I do
know how to tell Lisp how to do something very similar, which is to
have enclosingfunction treat the list '((expandedmacro1) ... ) as if
it were its list of parameters. You do this using the APPLY function:

(apply #'enclosingfunction '((expandedmacro1) ...))

is equivalent to

(enclosingfunction (expandedmacro1) ...)

and should do exactly what you want.

Cheers,
Pillsy