On 8/24/15 11:09 AM, Michal Minich wrote:
I'm thinking about ranges I can think of similar design of the input
range, but with different pros and cons. Obviously not for/in D.
Currently ranges has 3 primitive operations, and they can be translated
from foreach like:
for (auto __r = range; !__r.empty; __r.popFront())
{
auto e = __r.front;
...
}
I'm thinking of design where range would have only 2 primitive operations:
bool popFront() // returns true if current will have an element
front // it may be called only if popFrount (would) have
returned true
foreach would be translated to:
while (auto r = r.popFront())
{
auto e = __r.front;
...
}
This design results in following differences
1) 2 primitive operations (empty and popFront) are merge into one less
primitive
2) it will result in less calls per item (2 instead for 3)
3) it is not possible to "ask" a range if it's empty more times per
iteration of one item
This isn't very composable. If I call a function that consumes some
number of items from a range, that function needs to forward the
information back to me of whether the range is now empty or not.
4) it does _not_ requires range to be in "ready" state immediately after
construction. That means that popFront needs to be called firstly,
before front can be. This I feel is biggest change. Since D ranges are
required to have front ready immediately after their construction. Which
for some non trivial ranges can seem as less effective/convenient/expected.
So on the flip side, ranges that *could* be ready as soon as they are
created, must store some state that says popFront hasn't yet been
called. I find this requirement to be a wash implementation-wise, and
actually a negative API wise, since you as the consumer of the range
must carry the burden of storing whether it was empty the last time
popFront was called.
I would challenge you to write a wrapper for an array slice (yes, you
would need a wrapper, not just simple UFCS functions) and see whether
you think it's still worth it.
-Steve