On 13/07/10 17:23, Didier 'Ptitjes' wrote:
> All in all, breaking the ABI/API is not a problem, as we still have at
> least one anticipated round of developement where we do expect to break
> the ABI. So don't let that limit your imagination/creativity/engineering...
I've done some thinking and I'm somehow unhappy about current
Iterator<G> design (I was discussing it before but it wasn't so big
problem as it was on iterator-as-primary-thing-we-operate-on). I know
that would be a big change in interface so it may be something we should
be really careful.
The problem is that we have 2 somehow separated states:
- Before start or after delete when we point between elements
+---+---+---+---+ +---+---+---+---+
| | | | | | | | | |
+---+---+---+---+ +---+---+---+---+
^ ^
| |
- After start when we point at elements
+---+---+---+---+
| | | | |
+---+---+---+---+
^
|
Problems:
1. If we want to skip lets say odd elements from the beginning we have
to create a new GObject (which is not exactly lightweight). Instead if
we had a list:
+---+---+---+---+
| 1 | 3 | 2 | 4 |
+---+---+---+---+
We check if next element exists. Then we move onto it and checks if it
is odd. 1, 3 aren't - 2 and 4 are. So now we point at 2:
+---+---+---+---+
| 1 | 3 | 2 | 4 |
+---+---+---+---+
^
|
However if we would treat it as start of iterator we would get:
next() --> true
get() --> 4 (!!!)
next() --> false
skipWhile would not behave as iterator at all. (similar 'problem' I had
with ReverseIterator)
Solution:
a) Add is_pointing or similar property and check if the iterator is
pointing somewhere then perform is_next (breaks API/ABI and produces
horrible code)
b) Point always on element, past-the-end or before-the-beginning like in
C++/STL.
c) Just return a new iterator in skip operations.
d) Add get_next/lookahead methods
2. The remove method makes no sense for the many of iterators now. For
example:
Iterator<int> iter = new ArrayList(...).map(String.to_int);
if(iter.next()) {
iter.remove(); // ???
}
Yes - we can use assert_not_reached but... well what's the point of
method in interface for which 99% of implementation would have it.
(On second thought - many operations resulting in iterator would have
some corresponding element. Event to the extend of:
...() .map (String.to_int).remove_if ((x) => return x % 2 == 0)
// The same as ...() . remove_if ((x) => return x.to_int % 2 == 0))
3. first/last methods requires caching. I admit - they were my ideas but
I guess they were bad - or rather should be reversed.
If the Iterator<G> have first method it have to save all elements before
if iteration have side-effects. And in impure FP style it can:
iter.map((file) => {
stderr.printf("Read" + file);
return open(file).read_all()
});
As the point of doing interators is to do it on-the-fly I would suggest
moving first to BidirIterator<G> as it can be implemented in terms of
prev anyway.
4. Rather suggestion for vala: foreach should work for iterators.
Reggards
Attachment:
signature.asc
Description: OpenPGP digital signature