From: bufie
Subject: macros and variable arglist  (macro-newbie)
Date: 
Message-ID: <3_6rc.86189$iF6.7346441@attbi_s02>
Hi,

I'm having trouble getting a macro to work with an arbitrary number of
parameters (I can get it to work fine with a fixed number of params, or with
keys for each parameter).

I know there is a very simple answer, but I'm just not finding it!

a very simple example that will just print out the arglist:

(demacro mymacro (&rest args)
  `(let ((myargs ,args))
     (dolist (a myargs)
       (prin1 a))
     )
  )

If I call (mymacro "arg1" "arg2") I would expect it to print "arg1" "arg2"
but instead I get an error message:  "arg1" is invalid as a function.  So it
is apparently interpreting the list ("arg1" "arg2") as a function call
(right?).  So the simple question is: how do I get the arglist to the macro
into an internal macro var?  I tried ,@ags and that didn't work, either...

sorry to be dense.  thanks for your help!

bufie

From: Kaz Kylheku
Subject: Re: macros and variable arglist  (macro-newbie)
Date: 
Message-ID: <cf333042.0405201617.6673356b@posting.google.com>
"bufie" <·····@spamneggs.com> wrote in message news:<·······················@attbi_s02>...
> Hi,
> 
> I'm having trouble getting a macro to work with an arbitrary number of
> parameters (I can get it to work fine with a fixed number of params, or with
> keys for each parameter).
> 
> I know there is a very simple answer, but I'm just not finding it!
> 
> a very simple example that will just print out the arglist:
> 
> (demacro mymacro (&rest args)
>   `(let ((myargs ,args))
>      (dolist (a myargs)
>        (prin1 a))
>      )
>   )

Ugh, you have to close the parens on one line!

  (defmacro ...
    (let ...
      (dolist ...
        (prin1 ..)))) ;; <-- like that

 
> If I call (mymacro "arg1" "arg2") I would expect it to print "arg1" "arg2"
> but instead I get an error message:  "arg1" is invalid as a function.

That's right. The arguments to the macro are the unevaluated
expressions. Each expression, by itself, can be inserted into the
macro expansion such that it will be evaluated when that expansion is
evaluated. But the *list* of evaluable expressions is not itself an
expression!

For instance suppose the arguments are (+ 2 2) and (cons 'a nil). Both
of these are individually expressions that evaluate to 4 and (A)
respectively. However, if you take a list of them, namely ((+ 2 2)
(cons 'a nil)), it's not an expression that you can evaluate, because
(+ 2 2) is not a function name or lambda expression.

The trick is to generate the function call expression (list (+ 2 2)
(cons 'a nil)). When you evaluate that, the expressions (+ 2 2) and
(cons 'a nil) are now separately evaluated as arguments for calling
the LIST function.

To do that in your macro, you need the ,@ ``splicing unquote''
operator, like this:

 (defmacro mymacro (&rest args)
   `(let ((myargs (list ,@args))
      (dolist (a myargs)
        (prin1 a))))

The splicing unquote operator must occur in a list. The list is
unpacked and merged into the surrounding list. In the tail position,
the thing being spliced can be an atom:

   `(foo ,@(+ 2 2))  -> (FOO . 4)

Also, in the tail position, you can, instead of the splicing operator,
use the dotted notation plus regular unquote:

   `(list . ,args)


> So it
> is apparently interpreting the list ("arg1" "arg2") as a function call
> (right?).  So the simple question is: how do I get the arglist to the macro
> into an internal macro var?


> I tried ,@ags and that didn't work, either...

Because without the (list ,@args) surrounding it, it will just create
bad LET syntax! If the args are X Y Z, you get

   (LET ((MYARGS X Y Z)) ...)  ...) ;; result of ,@ splice

Oops! You want:

   (LET ((MYARGS (LIST X Y Z)) ...) ...)

When you are writing a macro, write down the expression you want the
macro user to write, and write down the expression that you want to
pop out of the macro. That will make it obvious what has to be done.
From: John Thingstad
Subject: Re: macros and variable arglist  (macro-newbie)
Date: 
Message-ID: <opr8ba3uappqzri1@mjolner.upc.no>
If you try to epand args like this you get

(let ((myargs (arg1 arg2)) ...
as you can see arg1 is interpreted as a function
If you want to interpret it as data quote it

(defmacro mymacro (&rest args)
`(let ((myargs ',args))
      ...

On Thu, 20 May 2004 18:42:07 GMT, bufie <·····@spamneggs.com> wrote:

> Hi,
>
> I'm having trouble getting a macro to work with an arbitrary number of
> parameters (I can get it to work fine with a fixed number of params, or  
> with
> keys for each parameter).
>
> I know there is a very simple answer, but I'm just not finding it!
>
> a very simple example that will just print out the arglist:
>
> (demacro mymacro (&rest args)
>   `(let ((myargs ,args))
>      (dolist (a myargs)
>        (prin1 a))
>      )
>   )
>
> If I call (mymacro "arg1" "arg2") I would expect it to print "arg1"  
> "arg2"
> but instead I get an error message:  "arg1" is invalid as a function.   
> So it
> is apparently interpreting the list ("arg1" "arg2") as a function call
> (right?).  So the simple question is: how do I get the arglist to the  
> macro
> into an internal macro var?  I tried ,@ags and that didn't work,  
> either...
>
> sorry to be dense.  thanks for your help!
>
> bufie
>
>



-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
From: bufie
Subject: Re: macros and variable arglist  (macro-newbie)
Date: 
Message-ID: <bw7rc.86410$xw3.4822319@attbi_s04>
doh!

Thanks, John!

"John Thingstad" <··············@chello.no> wrote in message
·····················@mjolner.upc.no...
> If you try to epand args like this you get
>
> (let ((myargs (arg1 arg2)) ...
> as you can see arg1 is interpreted as a function
> If you want to interpret it as data quote it
>
> (defmacro mymacro (&rest args)
> `(let ((myargs ',args))
>       ...
>
> On Thu, 20 May 2004 18:42:07 GMT, bufie <·····@spamneggs.com> wrote:
>
> > Hi,
> >
> > I'm having trouble getting a macro to work with an arbitrary number of
> > parameters (I can get it to work fine with a fixed number of params, or
> > with
> > keys for each parameter).
> >
> > I know there is a very simple answer, but I'm just not finding it!
> >
> > a very simple example that will just print out the arglist:
> >
> > (demacro mymacro (&rest args)
> >   `(let ((myargs ,args))
> >      (dolist (a myargs)
> >        (prin1 a))
> >      )
> >   )
> >
> > If I call (mymacro "arg1" "arg2") I would expect it to print "arg1"
> > "arg2"
> > but instead I get an error message:  "arg1" is invalid as a function.
> > So it
> > is apparently interpreting the list ("arg1" "arg2") as a function call
> > (right?).  So the simple question is: how do I get the arglist to the
> > macro
> > into an internal macro var?  I tried ,@ags and that didn't work,
> > either...
> >
> > sorry to be dense.  thanks for your help!
> >
> > bufie
> >
> >
>
>
>
> -- 
> Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/