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