Re: Gee Functional iterators



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



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]