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