From: charlie
Subject: Macro keywords become non-optional with &rest or &body?
Date: 
Message-ID: <1116589673.708610.208640@o13g2000cwo.googlegroups.com>
Is this correct? I'm a little confused, I'm trying to add a no-master
keyword to my def-ltk-dialog-class macro to allow for toplevels and
popmenus and such. I'm also trying to add a &rest/&body to allow the me
to do things that my macro doesn't support (yet).
Looking up macro lambda lists in HS has just added to my confusion as
it seems that the &rest parameter when the macro expands includes the
keywords as a p-list and it's invocation requires the &rest to be a
keyword argument. My mind is reeling at this point so I made a little
example:

(defmacro test-ll (req &rest bod &key k)
  `(list ',req ',k ',bod))

I would expect the following to yeild ('a 'k '(rest1 rest2)) but:

(test-ll 'a :k 'k 'rest1 'rest2)
=> Illegal keyword/value pair 'REST1, 'REST2 in argument list.
likewise
(test-ll 'a 'rest1 'rest2 :k 'k)

(test-ll 'a 'c)
=> GETF: the property list ('C) has an odd length

The only way to get it not to error is:
(test-ll 'a :k 'b :k 'rest1 :k 'rest2)
=> ('A 'B (:K 'B :K 'REST1 :K 'REST2))

This invocation just doesn't seem right (to my *highly* tuned lisp
sense ;-) ). Is there some lambda list feature I'm missing to allow me
to invoke it the way I'm expecting or is this just the way it is?

Thanks.
Charlieb

From: M Jared Finder
Subject: Re: Macro keywords become non-optional with &rest or &body?
Date: 
Message-ID: <-MGdncYiJvwGaxDfRVn-ig@speakeasy.net>
charlie wrote:
> Is this correct? I'm a little confused, I'm trying to add a no-master
> keyword to my def-ltk-dialog-class macro to allow for toplevels and
> popmenus and such. I'm also trying to add a &rest/&body to allow the me
> to do things that my macro doesn't support (yet).
> Looking up macro lambda lists in HS has just added to my confusion as
> it seems that the &rest parameter when the macro expands includes the
> keywords as a p-list and it's invocation requires the &rest to be a
> keyword argument. My mind is reeling at this point so I made a little
> example:
> 
> (defmacro test-ll (req &rest bod &key k)
>   `(list ',req ',k ',bod))
> 
> I would expect the following to yeild ('a 'k '(rest1 rest2)) but:
> 
> (test-ll 'a :k 'k 'rest1 'rest2)

Practical Common Lisp (http://www.gigamonkeys.com/book/) covers the 
function lambda list keywords in Chapter 5, Functions, section "Mixing 
Different Parameter Types".

Macro lambda list keywords act exactly the same, but with a few extra 
features (&whole, &body, destructuring).

   -- MJF
From: charlie
Subject: Re: Macro keywords become non-optional with &rest or &body?
Date: 
Message-ID: <1116601530.400763.198500@g44g2000cwa.googlegroups.com>
Interesting, now that the "why" makes sense I just have to worry about
the how.
Thanks,
Charlieb.
From: Joel Ray Holveck
Subject: Re: Macro keywords become non-optional with &rest or &body?
Date: 
Message-ID: <y7c64xa42zl.fsf@sindri.juniper.net>
> Interesting, now that the "why" makes sense I just have to worry about
> the how.

The usual convention with macros seems to be that, if you have both
"regular" arguments and a body, to put the arguments in a list, eg
  (defmacro foo ((x y) &body body)
    ...)
Not only does this make &key arguments usable, but it also lets Lisp
notify your macro users if they left out a required argument before
they started the body.

See also most of the WITH- macros in ANSI CL.

joelh
From: charlie
Subject: Re: Macro keywords become non-optional with &rest or &body?
Date: 
Message-ID: <1116853349.855180.140060@g47g2000cwa.googlegroups.com>
Yes, that's the one I went with. Strangely I hadn't noticed that most
of the with- macros do it this way too. Vindicated, excellent!

Cheers.
Charlie.
From: Lars Brinkhoff
Subject: Re: Macro keywords become non-optional with &rest or &body?
Date: 
Message-ID: <85is1eksox.fsf@junk.nocrew.org>
"charlie" <···············@gmail.com> writes:
> I'm trying to add a no-master keyword to my def-ltk-dialog-class
> macro to allow for toplevels and popmenus and such. I'm also trying
> to add a &rest/&body to allow the me to do things that my macro
> doesn't support (yet).
>
> (defmacro test-ll (req &rest bod &key k)
>   `(list ',req ',k ',bod))
>
> I would expect the following to yeild ('a 'k '(rest1 rest2))

No, with that lambda list shape, bod will include the keyword
arguments.  To avoid the error you're getting, add &allow-other-keys:

  (defmacro test-ll (req &rest bod &key k &allow-other-keys)
    `(list ',req ',k ',bod))

But you may want to do this instead:

  (defmacro test-ll ((req &key k) &body bod)
    `(list ',req ',k ',bod))

Of course, macro invokations will have to change to e.g.:

  (test-ll (a :k k)
    body1
    body2)
From: charlie
Subject: Re: Macro keywords become non-optional with &rest or &body?
Date: 
Message-ID: <1116596226.361989.251160@o13g2000cwo.googlegroups.com>
OK now it makes a little more sense. I'm still confused as to why it is
so but at least my code works now!
I went with the second version because I'm lazy and it looks just fine
in my examples.

Thanks,
Charlieb.
From: Tim X
Subject: Re: Macro keywords become non-optional with &rest or &body?
Date: 
Message-ID: <87r7g1qhv2.fsf@tiger.rapttech.com.au>
"charlie" <···············@gmail.com> writes:

> OK now it makes a little more sense. I'm still confused as to why it is
> so but at least my code works now!
> I went with the second version because I'm lazy and it looks just fine
> in my examples.
>
> Thanks,
> Charlieb.
>
I think the problem is simply that during evaluation, there is no way
to tell when the &rest arguments end and the &key arguments begin. I'd
recommend looking at Practical Common Lisp on-line at
http://www.gigamonkeys.com/book as it explains this.

Tim

-- 
Tim Cross
The e-mail address on this message is FALSE (obviously!). My real e-mail is
to a company in Australia called rapttech and my login is tcross - if you 
really need to send mail, you should be able to work it out!
From: Kent M Pitman
Subject: Re: Macro keywords become non-optional with &rest or &body?
Date: 
Message-ID: <u3bsgk8af.fsf@nhplace.com>
Tim X <····@spamto.devnul.com> writes:

> "charlie" <···············@gmail.com> writes:
> 
> > OK now it makes a little more sense. I'm still confused as to why it is
> > so but at least my code works now!
> > I went with the second version because I'm lazy and it looks just fine
> > in my examples.
> >
> > Thanks,
> > Charlieb.
> >
> I think the problem is simply that during evaluation, there is no way
> to tell when the &rest arguments end and the &key arguments begin. I'd
> recommend looking at Practical Common Lisp on-line at
> http://www.gigamonkeys.com/book as it explains this.

The &rest arguments don't end and the &key arguments don't begin, except
as an artifact of the program supplying them.

From the receiver's point of view, the issues are these:

 - Any time you use &rest, you can supply an arbitrary number 
   of arguments.

 - Any time you use &key, you must supply an even number of arguments,
   the odd arguments of which must be among the keys unless either
   &allow-other-keys is used in the formal arguments list or
   :allow-other-keys is used in the actual arguments list.

These two constraints combine, so that if you use both, you can supply
an arbitrary even number of arguments.  That is, you can't do:

 (defun foo (a b c &rest args &key x y z) ...)

and then do 

 (foo 3 4 5 6 7 8 :x 9 :z 14)

because it's not like it processes the rest and then the key.  Rather,
by including &key, you are saying "all the rest are taken key-style"
(and, hence, there are an even number of args), but I want to pick 
them up as a list.  That is, something more like:

 (foo 3 :x 9 :z 14)

Note that you still can't say

 (foo 3 :x 9 :z 14 :m 9)

unless you either use &allow-other-keys in the receiver or 
:allow-other-keys t in caller.
From: charlie
Subject: Re: Macro keywords become non-optional with &rest or &body?
Date: 
Message-ID: <1116853170.520422.228250@g14g2000cwa.googlegroups.com>
Thank-you for suck a succinct summary. I have a feeling that when my
head stops spinning that I may have learned something.

Charlie.