LOOP and destructuring
Author Message
LOOP and destructuring

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 ?

--

Mon, 05 Jul 2004 20:33:27 GMT
LOOP and destructuring

Quote:
>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.

Quote:
>                                                 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)) ...)

--

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.

Tue, 06 Jul 2004 00:41:35 GMT
LOOP and destructuring

Quote:

> (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.

Tue, 06 Jul 2004 00:48:02 GMT
LOOP and destructuring

Quote:

> >(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.

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

Exactly. I meant that.

Quote:
> 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.

--

Tue, 06 Jul 2004 00:58:15 GMT
LOOP and destructuring

Quote:

>> >(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

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

--

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.

Tue, 06 Jul 2004 04:03:08 GMT
LOOP and destructuring

Quote:

> 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.

Tue, 06 Jul 2004 07:00:55 GMT

 Page 1 of 1 [ 6 post ]

Relevant Pages