Re: LOOP blows!
- From: Kaz Kylheku <kkylheku@xxxxxxxxx>
- Date: Thu, 7 Feb 2008 21:03:21 -0800 (PST)
On Feb 7, 7:38 pm, Madhu <enom...@xxxxxxxx> wrote:
If you wanted this to return '(1 2 3) you should have written:
(loop with x = '(1 2 3) for y in x collect y)
But the point is that
(loop for x = '(1 2 3) for y in x collect y)
/does/ return (1 2 3) for me. I suspected that this is the cause of
the problem, which is why I presented that test case. (Though I
fumbled with that spurious DO).
* All variables are initialized first, regardless of where the establishing
clauses appear in the source. The order of initialization follows the
order of these clauses."
So X is initialized to NIL before entering entering the first
iteration.
Indeed yes, so what?
The first for clause will never terminate. The second for clause
terminates when there are no more elements to iterate over, as per
6.1.2.2 above when the list it is iterating over is empty.
X isn't the empty list any longer, because the first clause, FOR X =
'(1 2 3), assigns a value to X. This clause is not combined with the
second FOR Y clause using AND, so they do not work in parallel.
I understand that X is a local variable that starts out NIL. The first
FOR must change that by giving it a value.
Now, if I had
FOR X = '(1 2 3) AND Y IN X
then you would have a case. Now they are parallel, and so Y iterates
using the value of X that existed before the assignment of '(1 2 3),
the initial NIL. Thus the FOR Y IN clause instantly terminates and the
loop is dead on arrival.
I'd like to emphasise that there is no ambiguity in LOOP, the perceived
ambiguity comes from people expecting some behaviour without
understanding the well specified execution model.
Right, and ``People'' includes the ones implementing LOOP, apparently,
which is why we are getting different answers for some perfectly
innocuous code that ought to be portable.
It looks like LOOP is harder to get right than a lot of other parts of
Common Lisp! LOOP is historically a source of portability bugs.
--
Madhu
PS: If your goal was to return (1 2 3) you should not even start
considering this form of LOOP.
Even when what you wrote is translated to
DO* (do* ((x '(1 2 3) '(1 2 3))
(xtemp x (cdr xtemp))
(y (car x))
This is not how FOR IN works. It captures the value of the list
expression once, and then steps over /that/ list object, regardless of
what happens to the value of that original expression.
What you want above is:
(Y (CAR XTEMP))
You must use your hidden list iteration variable to set up the
successive values for Y, not make repeated references to the X
variable.
The logic you are describing has no hope of working; it's just
extracting (CAR X) on every iteration, and X doesn't change.
(ret))
((null xtemp) (reverse ret))
See, why are you using the hidden iteration variable XTEMP to figure
out when the list iteration ends, but using (CAR X) to actually pull
out the value?
The logic is inconsistent.
(push y ret))
all you can hope is for (1 1 1)
Nope. For instance:
(let ((list '(1 2 3)))
(loop for x in list collecting x do pop list))
should still produce (1 2 3), even though LIST changes throughout the
loop. The x variable iterates over the object that was initially
produced by LIST.
.
- Follow-Ups:
- Re: LOOP blows!
- From: Madhu
- Re: LOOP blows!
- References:
- LOOP blows!
- From: Kaz Kylheku
- Re: LOOP blows!
- From: Maciej Katafiasz
- Re: LOOP blows!
- From: Kaz Kylheku
- Re: LOOP blows!
- From: Madhu
- LOOP blows!
- Prev by Date: Re: LOOP blows!
- Next by Date: Re: LOOP blows!
- Previous by thread: Re: LOOP blows!
- Next by thread: Re: LOOP blows!
- Index(es):
Relevant Pages
|
|