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
be helpful, you can do:

  (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  
 
 [ 6 post ] 

 Relevant Pages 

1. LOOP destructuring and multiple values

2. Destructuring / pattern-matching (was: Multiple return values)

3. Destructuring / pattern-matching (was: Multiple return values)

4. destructuring-bind CLISP bug?

5. understanding destructuring-bind

6. destructuring in DEFMACRO lambda-lists

7. destructuring-bind

8. Destructuring problem

9. GCL does not have DESTRUCTURING-BIND?????

10. break one loop and skip one iteration of outer loop

11. 2 files: a loop within a loop??

12. Problem with loop inside other loop

 

 
Powered by phpBB® Forum Software