From: Frode Vatvedt Fjeld
Subject: Looping across a vector
Date: 
Message-ID: <2hd6zzpkgm.fsf@dslab7.cs.uit.no>
Should the result of

  (loop for x across (make-array 10 :fill-pointer 2) collect x)

really be #(nil nil), as the implementations I've tried seem to agree
on? Shouldn't all ten elements be collected?

The HyperSpec says this, in section 6.1.2.1.5:

  Iteration stops when there are no more elements in the supplied
  array that can be referenced.


Furthermore, clisp returns 5 for the following form, whereas ACL and
CMUCL returns 4:

  (loop for x across (make-array 10 :fill-pointer 5) as i upfrom 0
    finally (return i))

Is clisp wrong, are they all wrong for not returning 9 (or 10?), or
what?

-- 
Frode Vatvedt Fjeld

From: Thomas A. Russ
Subject: Re: Looping across a vector
Date: 
Message-ID: <ymiu1tbxmfx.fsf@sevak.isi.edu>
Frode Vatvedt Fjeld <······@acm.org> writes:


> Should the result of
> 
>   (loop for x across (make-array 10 :fill-pointer 2) collect x)
> 
> really be #(nil nil), as the implementations I've tried seem to agree
> on? Shouldn't all ten elements be collected?

Actually (nil nil) as a list

> The HyperSpec says this, in section 6.1.2.1.5:
> 
>   Iteration stops when there are no more elements in the supplied
>   array that can be referenced.

Right.  The fill-pointer indicates the logical end of the list.  Until
it is incremented, there are conceptually no elements beyond it.

> Furthermore, clisp returns 5 for the following form, whereas ACL and
> CMUCL returns 4:
> 
>   (loop for x across (make-array 10 :fill-pointer 5) as i upfrom 0
>     finally (return i))
> 
> Is clisp wrong, are they all wrong for not returning 9 (or 10?), or
> what?

I would say that clisp is wrong.  The iteration is supposed to terminate
when no more elements are available, and the Hyperspec says that
termination tests are done before the loop body executes, and stepping
of variables is the first thing in the loop body.

What answers do you get from the List case?

  (loop for x in (make-list 5) as i upfrom 0
        finally (return i))

For real fun try the following:

  (loop for x in (make-list 5) and i upfrom 0
        finally (return i))

  (loop for i upfrom 0 and x in (make-list 5)
        finally (return i))

  (loop for i upfrom 0 as x in (make-list 5)
        finally (return i))

All of MCL, CMUCL and ACL5 give me 4, 4, 5 as answers.  I wonder if it
should be 4, 4, 4 instead?  It would seem that you should have to do all
of the termination tests first, and then step variables.  In that case,
it shouldn't matter what connectives are used.

-Tom.

-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu    
From: Rahul Jain
Subject: Re: Looping across a vector
Date: 
Message-ID: <87k7u651ed.fsf@photino.sid.rice.edu>
···@sevak.isi.edu (Thomas A. Russ) writes:

>   (loop for i upfrom 0 as x in (make-list 5)
>         finally (return i))
> 
> All of MCL, CMUCL and ACL5 give me 4, 4, 5 as answers.  I wonder if it
> should be 4, 4, 4 instead?  It would seem that you should have to do all
> of the termination tests first, and then step variables.  In that case,
> it shouldn't matter what connectives are used.

As I understand it, "and" denotes clauses that should be executed in
parallel, akin to let. If there is no and, the clauses are executed in
order, akin to let*. Therefore, the above loop should terminate when
the list-traversal clause signals the end, which is after the numeric
incrementing clause executes.

-- 
-> -/-                       - Rahul Jain -                       -\- <-
-> -\- http://linux.rice.edu/~rahul -=-  ············@techie.com  -/- <-
-> -/- "I never could get the hang of Thursdays." - HHGTTG by DNA -\- <-
|--|--------|--------------|----|-------------|------|---------|-----|-|
   Version 11.423.999.221020101.23.50110101.042
   (c)1996-2002, All rights reserved. Disclaimer available upon request.
From: Tim Moore
Subject: Re: Looping across a vector
Date: 
Message-ID: <a2pscl$p4h$0@216.39.145.192>
In article <··············@dslab7.cs.uit.no>, "Frode Vatvedt Fjeld"
<······@acm.org> wrote:


> Should the result of
> 
>   (loop for x across (make-array 10 :fill-pointer 2) collect x)
> really be #(nil nil), as the implementations I've tried seem to agree
> on? 

Yes.  Elements above the fill pointer aren't active, so it doesn't make
sense to visit them.

>Shouldn't all ten elements be collected?  The HyperSpec says this,
> in section 6.1.2.1.5:
>   Iteration stops when there are no more elements in the supplied array
>   that can be referenced.

You might think it's confusing in that elements above the fill pointer
can be referenced by aref, but I think the meaning here is "can be
referenced because they are active."  Fill pointers would be much less
useful if LOOP ignored them.

> Furthermore, clisp returns 5 for the following form, whereas ACL and
> CMUCL returns 4:
> 
>   (loop for x across (make-array 10 :fill-pointer 5) as i upfrom 0
>     finally (return i))
> Is clisp wrong, are they all wrong for not returning 9 (or 10?), or
> what?

The ACL/CMUCL result is least surprising to me.  Stepping occurs
sequentially; "For these clauses, iteration terminates when a local variable reaches
some supplied value or when some  other loop clause terminates
iteration."  I interpret that to mean "right after the variable is
stepped."

Tim
From: Harald Hanche-Olsen
Subject: Re: Looping across a vector
Date: 
Message-ID: <pcog04uw3f7.fsf@thoth.math.ntnu.no>
+ "Tim Moore" <·····@bricoworks.com>:

| In article <··············@dslab7.cs.uit.no>, "Frode Vatvedt Fjeld"
| <······@acm.org> wrote:
| 
| 
| > Should the result of
| > 
| >   (loop for x across (make-array 10 :fill-pointer 2) collect x)
| > really be #(nil nil), as the implementations I've tried seem to
| > agree on?
| 
| Yes.  Elements above the fill pointer aren't active, so it doesn't
| make sense to visit them.

I think we can all agree on that.  However, the words in the standard
are "can be referenced", not "are active".  The case of aref seems a
clear example that inactive elements can be referenced.  But I'll bet
that the intention is as you say - in fact, section 3.6 (Traversal
Rules and Side Effects) states:

  Array traversal 

     For array traversal operations, the array is not allowed to be
     adjusted and its fill pointer, if any, is not allowed to be
     changed.

Now, they would hardly have mentioned the fill pointer here unless it
was meant to be obeyed, right?  And there is a link to 3.6 from
6.1.1.8 in the section on LOOP, so one can hardly argue that section
3.6 does not apply in this case.

My tentative conclusion is that the choice of words in 6.1.2.1.5 (The
for-as-across subclause) is probably a bug in the standard, and has
probably been recognized as such by all the implementors.  (The bug
could have been fixed by inserting the single word "active" in the
right place.)

If we ask again in a week, I am sure Kent will give us the real scoop,
in more detail than any of us ever wanted.  8-)

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Yes it works in practice - but does it work in theory?
From: Chris Vogt
Subject: Re: Looping across a vector
Date: 
Message-ID: <3C507766.2090608@cox.net>
Frode Vatvedt Fjeld wrote:

> Should the result of
> 
>   (loop for x across (make-array 10 :fill-pointer 2) collect x)

 >
 > really be #(nil nil), as the implementations I've tried seem to agree
 > on? Shouldn't all ten elements be collected?

CL-USER 21 > (make-array 10 :fill-pointer 2)
#(NIL NIL)
CL-USER 22 > (loop for x across * collect x)
(NIL NIL)

You need to read up on what the meaning of :fill-pointer is.