> Even C++ realized this fact (badly) with iterators.
would you mind clarifying that a bit (or a bunch) ? afaik, STL cleanly separates the notion of structures and algorithms that operate on those structures via iterators.
I'm not the grandparent poster, but one classic problem with STL iterators is that they always have to come in pairs. If you think about it, most STL algorithms don't really work on iterators, they work on ranges that happen to be defined by pairs of iterators. That makes it hard to compose operations, makes it hard to work with infinite streams, and makes it possible to screw up and write something like std::transform(v1.begin(), v2.end()).
Have a look at Alexandrescu's work on ranges in D for a more modern exploration of the same concept.
What is wrong with STL iterators? To see the shortcomings, let's dream up a better one and then compare.
Our hypothetical interface to iterators will have the following methods:
bool not_done(); // Is the iterator done?
void next(); // Move to the next value. Throws exception if done.
Foo value(); // What value do we have? Throws exception if done.
Our data structures will support the method iterator() that is the moral equivalent of begin().
We already have the equivalent of STL iterators. You just change:
for (data_structure::iterator it = foo.begin(); it != foo.end(); ++it) { /* do stuff with it / }
to
for (iterator< fooish > it = foo.iterator(); it.not_done(); it.next()) { /* do stuff with it.value() */ }
So far uninteresting. But with this new interface we can add four interesting templates in a straightforward matter.
1. Take an iterator< fooish > and a function that maps things of type fooish to type barish, then produce an iterator< barish >.
2. Take an iterator< fooish >, and a function that maps fooish to bool, then produces an iterator that gives you just the ones that mapped to true.
3. (Generalization of the first two.) Take an iterator that produces things of type fooish, and a function that maps fooish to iterator< barish >, and returns an iterator< barish > that just maps each value from the first to all of the bars that it produces.
4. Take an object with a method that produces things of type fooish, and produce an iterator< fooish >.
These are all simple to define given this interface. What do they allow us to do? Well the article that introduced me to the idea of iterators was http://perl.plover.com/Stream/stream.html - absolutely everything in that article is straightforward with the interface that I described and absolutely none of it is easy with STL iterators. (It is all still actually possible, but tricky. Proving that fact is left as an exercise to the reader, at which point you'll know why people don't tend to think about problems that way in C++.)
would you mind clarifying that a bit (or a bunch) ? afaik, STL cleanly separates the notion of structures and algorithms that operate on those structures via iterators.
thanks !