From: Mikalai
Subject: Need help with use of inner-lambda lists in defmacro
Date: 
Message-ID: <1140034142.024621.256050@g43g2000cwa.googlegroups.com>
Hi,
In many places examples of use inner-lambda lists are something like
 (defmacro foo ((a b) &optional ((a d)) ....)
 and these are well described.
But these seem to not help me (am I missing something?) in use of
 (defmacro foo (&rest (a b &body c)) ....)
 i.e. how one can use a, b & c from an inner list, which should happen
many or zero times (under option rest)? What should I write as a body
of a macro? Let's say, for every list I want to put `(boo ,a ,b ,@c).
How should it look like?
Thank you in advance,
Mikalai

From: Pascal Bourguignon
Subject: Re: Need help with use of inner-lambda lists in defmacro
Date: 
Message-ID: <87wtfw73xy.fsf@thalassa.informatimago.com>
"Mikalai" <········@yahoo.com> writes:

> Hi,
> In many places examples of use inner-lambda lists are something like
>  (defmacro foo ((a b) &optional ((a d)) ....)
>  and these are well described.
> But these seem to not help me (am I missing something?) in use of
>  (defmacro foo (&rest (a b &body c)) ....)

This is not valid syntax, the grammar rule is:

restvar::= [{&rest | &body} var] 

and var must be a symbol.
http://www.lispworks.com/documentation/HyperSpec/Body/03_dd.htm

>  i.e. how one can use a, b & c from an inner list, which should happen
> many or zero times (under option rest)? What should I write as a body
> of a macro? Let's say, for every list I want to put `(boo ,a ,b ,@c).
> How should it look like?

You can write:

(defmacro foo (&rest [a-b-&body-c]*)
  (loop for (a b . c) in [a-b-&body-c]* 
        ... ))

for example:

(defmacro foo (&rest [a-b-&body-c]*)
  `(progn 
     ,@(loop for (a b . c) in [a-b-&body-c]* 
             collect `(boo ,a ,b ,@c)))

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

In a World without Walls and Fences, 
who needs Windows and Gates?
From: Mikalai
Subject: Re: Need help with use of inner-lambda lists in defmacro
Date: 
Message-ID: <1140036867.872990.197240@g44g2000cwa.googlegroups.com>
> >  (defmacro foo (&rest (a b &body c)) ....)

>This is not valid syntax, the grammar rule is:
>restvar::= [{&rest | &body} var]

Aha! So, there is no free-lunch in &rest -- decompose lists yourself!!

Thank you, Pascal.
From: Peter Seibel
Subject: Re: Need help with use of inner-lambda lists in defmacro
Date: 
Message-ID: <m2y80c2smg.fsf@gigamonkeys.com>
Pascal Bourguignon <······@informatimago.com> writes:

> "Mikalai" <········@yahoo.com> writes:
>
>> Hi,
>> In many places examples of use inner-lambda lists are something like
>>  (defmacro foo ((a b) &optional ((a d)) ....)
>>  and these are well described.
>> But these seem to not help me (am I missing something?) in use of
>>  (defmacro foo (&rest (a b &body c)) ....)
>
> This is not valid syntax, the grammar rule is:
>
> restvar::= [{&rest | &body} var] 
>
> and var must be a symbol.
> http://www.lispworks.com/documentation/HyperSpec/Body/03_dd.htm

But you neglect:

  3.4.4.1 Destructuring by Lambda Lists

  Anywhere in a macro lambda list where a parameter name can appear,
  and where ordinary lambda list syntax (as described in Section 3.4.1
  (Ordinary Lambda Lists)) does not otherwise allow a list, a
  destructuring lambda list can appear in place of the parameter name.
  When this is done, then the argument that would match the parameter
  is treated as a (possibly dotted) list, to be used as an argument
  list for satisfying the parameters in the embedded lambda list. This
  is known as destructuring.

So given that we can write:

  (defmacro foo (&rest x) ...)

we can also write:

  (defmacro foo (&rest (a b &body c)) ...)

replacing X with the destructuring lambda list (A B &BODY C).

However I don't think that does what the OP actually wanted; for that
he probably needs something like what you suggest.

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Pascal Bourguignon
Subject: Re: Need help with use of inner-lambda lists in defmacro
Date: 
Message-ID: <87k6bw6wj8.fsf@thalassa.informatimago.com>
Peter Seibel <·····@gigamonkeys.com> writes:
> But you neglect:
>
>   3.4.4.1 Destructuring by Lambda Lists
>
>   Anywhere in a macro lambda list where a parameter name can appear,
>   and where ordinary lambda list syntax (as described in Section 3.4.1
>   (Ordinary Lambda Lists)) does not otherwise allow a list, a
>   destructuring lambda list can appear in place of the parameter name.
>   When this is done, then the argument that would match the parameter
>   is treated as a (possibly dotted) list, to be used as an argument
>   list for satisfying the parameters in the embedded lambda list. This
>   is known as destructuring.
>
> So given that we can write:
>
>   (defmacro foo (&rest x) ...)
>
> we can also write:
>
>   (defmacro foo (&rest (a b &body c)) ...)
>
> replacing X with the destructuring lambda list (A B &BODY C).

Yes, I neglected it.  


IIUC, the meaning of 

   (defmacro foo (&rest (a b &body c)) ...)

will be equivalent to:

   (defmacro foo (a b &body c) ...)

Let's try it:

CL-USER> (defmacro foo (&rest (a b &body c)) `(quote (:a ,a :b ,b :c ,@c)))
FOO
CL-USER> (foo a b c d e)
(:A A :B B :C C D E)
CL-USER> (defmacro foo (a b &body c) `(quote (:a ,a :b ,b :c ,@c)))
FOO
CL-USER> (foo a b c d e)
(:A A :B B :C C D E)

Right.


> However I don't think that does what the OP actually wanted; for that
> he probably needs something like what you suggest.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

This universe shipped by weight, not volume.  Some expansion may have
occurred during shipment.
From: Kenny Tilton
Subject: Re: Need help with use of inner-lambda lists in defmacro
Date: 
Message-ID: <VmSIf.193$cF5.32@news-wrt-01.rdc-nyc.rr.com>
Mikalai wrote:
> Hi,
> In many places examples of use inner-lambda lists are something like
>  (defmacro foo ((a b) &optional ((a d)) ....)
>  and these are well described.
> But these seem to not help me (am I missing something?) in use of
>  (defmacro foo (&rest (a b &body c)) ....)
>  i.e. how one can use a, b & c from an inner list, which should happen
> many or zero times (under option rest)? What should I write as a body
> of a macro? Let's say, for every list I want to put `(boo ,a ,b ,@c).
> How should it look like?
> Thank you in advance,
> Mikalai
> 

Try destructuring-bind:

(let ((x '((a b :k1 c)(d e :k1 f))))
   (dolist (y x)
     (destructuring-bind (p1 p2 &key k1) y
         (print (list p1 p2 k1)))))

In your case, the rest parameter becomes X in my example.

ken
From: Mikalai
Subject: Re: Need help with use of inner-lambda lists in defmacro
Date: 
Message-ID: <1140104412.793196.171370@g14g2000cwa.googlegroups.com>
Kenny Tilton wrote:

> Try destructuring-bind:
>
> (let ((x '((a b :k1 c)(d e :k1 f))))
>    (dolist (y x)
>      (destructuring-bind (p1 p2 &key k1) y
>          (print (list p1 p2 k1)))))
>
> In your case, the rest parameter becomes X in my example.
> 

Yes, I'll follow you example. Thank you.
Mikalai
From: Kenny Tilton
Subject: Re: Need help with use of inner-lambda lists in defmacro
Date: 
Message-ID: <k34Jf.225$cF5.52@news-wrt-01.rdc-nyc.rr.com>
Mikalai wrote:
> Kenny Tilton wrote:
> 
> 
>>Try destructuring-bind:
>>
>>(let ((x '((a b :k1 c)(d e :k1 f))))
>>   (dolist (y x)
>>     (destructuring-bind (p1 p2 &key k1) y
>>         (print (list p1 p2 k1)))))
>>
>>In your case, the rest parameter becomes X in my example.
>>
> 
> 
> Yes, I'll follow you example. 


btw, if your rest param values will have structure that complicated, it 
is possible you do better by dividing the work between two macros, so 
that the resulting source might looklike:

(defgroup xxx (option :k1 k1 :k2 k2)
    (defitem xx1 (....) ...)
    (defitem xx2 (....) ...))


ken
From: Mikalai
Subject: Re: Need help with use of inner-lambda lists in defmacro
Date: 
Message-ID: <1140152265.392764.110110@g44g2000cwa.googlegroups.com>
Kenny Tilton wrote:
> btw, if your rest param values will have structure that complicated, it
> is possible you do better by dividing the work between two macros, so
> that the resulting source might looklike:
>
> (defgroup xxx (option :k1 k1 :k2 k2)
>     (defitem xx1 (....) ...)
>     (defitem xx2 (....) ...))

defgroup? defitem? Are these standard CL? I seem unable to locate them,
neither in hyperspec, nor in CLtheLang.
From: Kenny Tilton
Subject: Re: Need help with use of inner-lambda lists in defmacro
Date: 
Message-ID: <cbeJf.271$cF5.32@news-wrt-01.rdc-nyc.rr.com>
Mikalai wrote:
> Kenny Tilton wrote:
> 
>>btw, if your rest param values will have structure that complicated, it
>>is possible you do better by dividing the work between two macros, so
>>that the resulting source might looklike:
>>
>>(defgroup xxx (option :k1 k1 :k2 k2)
>>    (defitem xx1 (....) ...)
>>    (defitem xx2 (....) ...))
> 
> 
> defgroup? defitem? Are these standard CL? I seem unable to locate them,
> neither in hyperspec, nor in CLtheLang.
> 

No, there is just a long tradition of starting defining macros with DEF, 
and I just made up DEFGROUP and DEFITEM as two illustrative but made up 
macro names.

I was just trying to make clear what I meant by dividing things up into 
two macros. If you have a rest arg where each element is going to be of 
the same structure and be fairly hairy at that (or you would not need 
destructuring-bind) then I imagine that the one DEF-EVERYTHING macro you 
are working on might be easier to develop as two, and outer macro for 
the whole, and a second macro to express each of the rest elements.

If you are still confused, just forget I said anything, it was just a 
style thing. Time enough for that later.

ken