From: Vladimir Zolotykh
Subject: LOOP and destructuring
Date: 
Message-ID: <3C46C497.A8829735@eurocom.od.ua>
Consider the following

(defun bar ()
  (loop
      for (c &key a) in '(('a :a 10) ('b :a 20) ('c))
      do (format t "c=~A a=~A~%" c a)))

Is such using of LOOP destructuring facility legal? May I put
equal sign between it and DESTRUCTURING-BIND ?

-- 
Vladimir Zolotykh                         ······@eurocom.od.ua

From: Barry Margolin
Subject: Re: LOOP and destructuring
Date: 
Message-ID: <39D18.3$Gk3.28868@burlma1-snr2>
In article <·················@eurocom.od.ua>,
Vladimir Zolotykh  <······@eurocom.od.ua> wrote:
>Consider the following
>
>(defun bar ()
>  (loop
>      for (c &key a) in '(('a :a 10) ('b :a 20) ('c))
>      do (format t "c=~A a=~A~%" c a)))
>
>Is such using of LOOP destructuring facility legal? 

Yes, but it probably doesn't do what you expect.  It's equivalent to:

(loop for c in '('a 'b 'c)
      for &key in '(:a :b nil)
      for a in '(10 20 nil)
  do (format t "c=~A a=~A~%" c a))

I suspect you also didn't really want the inner quotes on 'a, 'b, and 'c,
since you're already quoting the list.

>						     May I put
>equal sign between it and DESTRUCTURING-BIND ?

I don't understand this question.  You don't have a DESTRUCTURING-BIND in
your code, so where are you talking about putting the equal sign?  If
you're asking "Is LOOP destructuring the same as DESTRUCTURING-BIND?", the
answer is that LOOP's destructuring is much simpler.  It just does simple
structural mapping between the destructuring pattern and the values it's
being bound to.  It is also more lenient of differences: extra variables
get bound to NIL, extra values are ignored.  It also supports dotted lists,
e.g.

(loop for (a . b) in '((1 . 2) (3 . 4)) ...)

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Vladimir Zolotykh
Subject: Re: LOOP and destructuring
Date: 
Message-ID: <3C4702A7.80FF23C8@eurocom.od.ua>
Barry Margolin wrote:
> 
> >(defun bar ()
> >  (loop
> >      for (c &key a) in '(('a :a 10) ('b :a 20) ('c))
> >      do (format t "c=~A a=~A~%" c a)))
> >
> >Is such using of LOOP destructuring facility legal?
> 
> Yes, but it probably doesn't do what you expect.  It's equivalent to:
> 
> (loop for c in '('a 'b 'c)
>       for &key in '(:a :b nil)
>       for a in '(10 20 nil)
>   do (format t "c=~A a=~A~%" c a))
> 
> I suspect you also didn't really want the inner quotes on 'a, 'b, and 'c,
> since you're already quoting the list.

You're right. I don't need it.

> you're asking "Is LOOP destructuring the same as DESTRUCTURING-BIND?", the

Exactly. I meant that.

> get bound to NIL, extra values are ignored.  It also supports dotted lists,

Understood. 
  for (c . rest) in '((a :a 10) (b :a 20) (c))
  do (format t "c=~A a=~A~%" c (getf rest :a))))
suits me.

-- 
Vladimir Zolotykh                         ······@eurocom.od.ua
From: Barry Margolin
Subject: Re: LOOP and destructuring
Date: 
Message-ID: <06G18.19$Gk3.35609@burlma1-snr2>
In article <·················@eurocom.od.ua>,
Vladimir Zolotykh  <······@eurocom.od.ua> wrote:
>Barry Margolin wrote:
>> 
>> >(defun bar ()
>> >  (loop
>> >      for (c &key a) in '(('a :a 10) ('b :a 20) ('c))
>> >      do (format t "c=~A a=~A~%" c a)))
>> >
>> >Is such using of LOOP destructuring facility legal?
>> 
>> Yes, but it probably doesn't do what you expect.  It's equivalent to:
>> 
>> (loop for c in '('a 'b 'c)
>>       for &key in '(:a :b nil)
>>       for a in '(10 20 nil)
>>   do (format t "c=~A a=~A~%" c a))
>> 
>> I suspect you also didn't really want the inner quotes on 'a, 'b, and 'c,
>> since you're already quoting the list.
>
>You're right. I don't need it.
>
>> you're asking "Is LOOP destructuring the same as DESTRUCTURING-BIND?", the
>
>Exactly. I meant that.
>
>> get bound to NIL, extra values are ignored.  It also supports dotted lists,
>
>Understood. 
>  for (c . rest) in '((a :a 10) (b :a 20) (c))
>  do (format t "c=~A a=~A~%" c (getf rest :a))))
>suits me.

If it gets more complex, so that the full power of DESTRUCTURING-BIND would
be helpful, you can do:

  (loop for l in '(...)
       do (destructuring-bind (c &key a) l
	    (format t "c=~A a=~A~%" c a)))

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Arthur Lemmens
Subject: Re: LOOP and destructuring
Date: 
Message-ID: <3C4757A7.3D896FA@xs4all.nl>
Barry Margolin wrote:

> If it gets more complex, so that the full power of DESTRUCTURING-BIND would
> be helpful, you can do:
> 
>   (loop for l in '(...)
>        do (destructuring-bind (c &key a) l
>             (format t "c=~A a=~A~%" c a)))

Yes. But then there's no easy way to use the 'full power of' LOOP to 
do something with the bindings of DESTRUCTURING-BIND. 

This is one case where Jonathan Amsterdam's ITERATE shows its advantages 
over LOOP. It allows you to do stuff like:

  (iterate (for item in list)
    (destructuring-bind (c &key (a 0) (b 0))
        item
      (minimize a into min-a)
      (maximize b into max-b) 
      (collect c into list-c))
    ...)

ITERATE can do this because it 'looks inside' its clauses.
From: Arthur Lemmens
Subject: Re: LOOP and destructuring
Date: 
Message-ID: <3C470042.1D478754@xs4all.nl>
Vladimir Zolotykh wrote:

> (defun bar ()
>   (loop
>       for (c &key a) in '(('a :a 10) ('b :a 20) ('c))
>       do (format t "c=~A a=~A~%" c a)))
> 
> Is such using of LOOP destructuring facility legal? 

It's conforming, and in this case it will even do what you expect it
to do. But that's just an accident. The relevant part of CLHS 
(6.1.1.7) doesn't say that LOOP destructuring works like 
DESTRUCTURING-BIND. Instead, it explicitly says how it does work:

  Destructuring allows binding of a set of variables to a corresponding 
  set of values anywhere that a value can normally be bound to a single 
  variable. During loop expansion, each variable in the variable list 
  is matched with the values in the values list. If there are more 
  variables in the variable list than there are values in the values
  list, the remaining variables are given a value of nil. If there are 
  more values than variables listed, the extra values are discarded. 

This means that, in your example, &KEY is a variable just like A and C.
In your example it gets bound to :A, :A and NIL.

Maybe the following example can show you the difference between your
expectations and the way it really works:

  (defun oh-oh ()
    (loop
        for (c &key a b) in '((1 :b 10) (2 :b 20 :a 2) (3))
        collect (list c a b)))

This will return:
  ((1 10 NIL) (2 20 :A) (3 NIL NIL))
and *not*
  ((1 NIL 10) (2 2 20) (3 NIL NIL))
as you might expect.