Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

The behaviour of iterators

5 views
Skip to first unread message

Dan Sugalski

unread,
Jun 14, 2004, 1:11:32 PM6/14/04
to perl6-i...@perl.org
Once we decide how to *get* these things (see the previous e-mail) we
need to decide how they should work. We can fiddle around, but
honestly the scheme:

1) They act as arrays--if you want the 18th element in the iterator,
access it directly
2) They have 'next', 'previous', 'first', 'last', and 'reset' methods
to get the next, previous, first, or last element in the iterator, or
to reset the iterator to the beginning. Next, last, and reset change
the internal current element pointer, first and last don't.

Sane? The only downside I can see is one of speed, since method calls
are a bit costly.
--
Dan

--------------------------------------it's like this-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk

Matt Fowles

unread,
Jun 14, 2004, 2:15:26 PM6/14/04
to Dan Sugalski, perl6-i...@perl.org
Dan~

Just a few questions.

Dan Sugalski wrote:

> 2) They have 'next', 'previous', 'first', 'last', and 'reset' methods
> to get the next, previous, first, or last element in the iterator, or
> to reset the iterator to the beginning. Next, last, and reset change
> the internal current element pointer, first and last don't.

Do you mean next, previous, reset?


What about those data structures that can only be iterated in one
direction easily (such as a singly linked list)? Should they implement
previous in the slow and painful way and hope no one calls it? Should
they throw an exception? Might it be worthwhile to have two different
types of iterators (those that only go one direction and those that go
both)?

Matt


Dan Sugalski

unread,
Jun 14, 2004, 2:38:42 PM6/14/04
to Matt Fowles, perl6-i...@perl.org
At 1:15 PM -0500 6/14/04, Matt Fowles wrote:
>Dan~
>
>Just a few questions.
>
>>Dan Sugalski wrote:
>>
>>2) They have 'next', 'previous', 'first', 'last', and 'reset'
>>methods to get the next, previous, first, or last element in the
>>iterator, or to reset the iterator to the beginning. Next, last,
>>and reset change the internal current element pointer, first and
>>last don't.
>
>Do you mean next, previous, reset?
>

D'oh! Yes.

>What about those data structures that can only be iterated in one
>direction easily (such as a singly linked list)? Should they
>implement previous in the slow and painful way and hope no one calls
>it? Should they throw an exception? Might it be worthwhile to have
>two different types of iterators (those that only go one direction
>and those that go both)?

Exceptions for unimplemented behaviour is just fine. I should've
specified. (I can see defining a basic and extended iterator protocol
for this)

Luke Palmer

unread,
Jun 14, 2004, 3:08:53 PM6/14/04
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski writes:
> Once we decide how to *get* these things (see the previous e-mail) we
> need to decide how they should work. We can fiddle around, but
> honestly the scheme:
>
> 1) They act as arrays--if you want the 18th element in the iterator,
> access it directly
> 2) They have 'next', 'previous', 'first', 'last', and 'reset' methods
> to get the next, previous, first, or last element in the iterator, or
> to reset the iterator to the beginning. Next, last, and reset change
> the internal current element pointer, first and last don't.

Why not take a page from C++ and call "previous" and "next" C<inc> and
C<dec>, and then C<deref> to get what it points to. The ops are already
there. Not sure about "reset" though.

Luke

Dan Sugalski

unread,
Jun 14, 2004, 3:29:08 PM6/14/04
to Luke Palmer, perl6-i...@perl.org

Because ++ and -- affect the value not the container. (There are days
when I think "C++ does it like..." is the near-perfect argument
against doing it one particular way... :) Next and previous are
actions on the container.

Luke Palmer

unread,
Jun 14, 2004, 11:04:26 PM6/14/04
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski writes:
> At 1:08 PM -0600 6/14/04, Luke Palmer wrote:
> >Dan Sugalski writes:
> >> Once we decide how to *get* these things (see the previous e-mail) we
> >> need to decide how they should work. We can fiddle around, but
> >> honestly the scheme:
> >>
> >> 1) They act as arrays--if you want the 18th element in the iterator,
> >> access it directly
> >> 2) They have 'next', 'previous', 'first', 'last', and 'reset' methods
> >> to get the next, previous, first, or last element in the iterator, or
> >> to reset the iterator to the beginning. Next, last, and reset change
> >> the internal current element pointer, first and last don't.
> >
> >Why not take a page from C++ and call "previous" and "next" C<inc> and
> >C<dec>, and then C<deref> to get what it points to.
>
> Because ++ and -- affect the value not the container. (There are days
> when I think "C++ does it like..." is the near-perfect argument
> against doing it one particular way... :)

Heh, yeah.

> Next and previous are actions on the container.

Then how, if we have an array of iterators, do we increment an internal
iterator from an external one. That is:

@foo = (1..5);
@bar = map { @foo.iter($_) } reverse 0..4; # make an array of iterators

for @bar ¥ 0... -> $x, $c {
if something($x) {
@bar[$c].next;
}
}

Without that awful reference of $c (awful not in a stylistic way, but in
a I-have-to-keep-the-index-around-too-wtf kind of way).

I'm arguing for an iterator to be an I<explicit> pointer, one that you
have to dereference, for this reason.

Luke

Dave Whipp

unread,
Jun 14, 2004, 5:06:40 PM6/14/04
to perl6-i...@perl.org
"Dan Sugalski" <d...@sidhe.org> wrote in message
news:a06110411bcf3ac90dbe4@[10.0.1.3]...

> >Why not take a page from C++ and call "previous" and "next" C<inc> and
> >C<dec>, and then C<deref> to get what it points to.
>
> Because ++ and -- affect the value not the container. (There are days
> when I think "C++ does it like..." is the near-perfect argument
> against doing it one particular way... :) Next and previous are
> actions on the container.

Whatever you name the next/previous operations, you need a way to
distinguish operations on the container from operations on the containee --
i.e. the C<deref> operator. Otherwise how would you iterate over a list of
iterators? And if you're going to have a deref operator, how much benefit do
you actually derive from having ops like C<inc> and C<dec> do an auto-deref.

Personally, I like the flexibility of the C++ approach (though some of its
limitations will hopefully be fixed in a future iteration of the standard).
Being able to add/subtract values other than 'one' to/from an iterator can
be useful, especially when iterating over an array. Then C<reset> can be
implemented by subtracting the current C<pos>; and C<last> is implemented by
adding "size-pos" (modulo an out-by-one error).

Incidentally, the ability to implement C<reset> implies that an iterator has
some way of finding its parent container. This adds an overhead, which is
probably why C++ doesn't do this. A lightweight implementation requires the
client-code to track the container, and then add/subtract methods are more
compelling than next/prev, because they enable reset/last to be higher level
concepts. Does/will parrot do run-time bounds checking to ensure you don't
run off the end of a container?


Dave.


Dan Sugalski

unread,
Jun 15, 2004, 11:55:22 AM6/15/04
to Dave Whipp, perl6-i...@perl.org
At 2:06 PM -0700 6/14/04, Dave Whipp wrote:
>"Dan Sugalski" <d...@sidhe.org> wrote in message
>news:a06110411bcf3ac90dbe4@[10.0.1.3]...
>> >Why not take a page from C++ and call "previous" and "next" C<inc> and
>> >C<dec>, and then C<deref> to get what it points to.
>>
>> Because ++ and -- affect the value not the container. (There are days
>> when I think "C++ does it like..." is the near-perfect argument
>> against doing it one particular way... :) Next and previous are
>> actions on the container.
>
>Whatever you name the next/previous operations, you need a way to
>distinguish operations on the container from operations on the containee --
>i.e. the C<deref> operator. Otherwise how would you iterate over a list of
>iterators?

Erm... you iterate over the list, and as it returns its contents you
iterate over that?

>Personally, I like the flexibility of the C++ approach (though some of its
>limitations will hopefully be fixed in a future iteration of the standard).
>Being able to add/subtract values other than 'one' to/from an iterator can
>be useful, especially when iterating over an array. Then C<reset> can be
>implemented by subtracting the current C<pos>; and C<last> is implemented by
>adding "size-pos" (modulo an out-by-one error).

These are just methods. (I don't believe I just said that...) We can
always enhance the protocol later.

>Incidentally, the ability to implement C<reset> implies that an iterator has
>some way of finding its parent container.

Hell, the ability of iterators to iterate implies that the iterator
has a hold on its parent container. This is just fine with me. (And
it makes sense as the normal way to iterate over a container--it's
the way that springs to mind first, at least for me)

0 new messages