On Thursday, 2 June 2016 at 12:51:18 UTC, Steven Schveighoffer
wrote:
1. front gets you the current element of the range. Calling
front multiple times without calling popFront should get you
the same value.
2. popFront moves you to the next element of the range if it
exists.
Agreed. To quote Ali,
* empty: specifes whether the range is empty; it must return true
when the
range is considered to be empty, and false otherwise
* front: provides access to the element at the beginning of the
range
* popFront(): shortens the range from the beginning by removing
the first element
However, there are some ranges which can violate this. For
example map:
...
But I consider this a programming error.
Completely agree. Comparing to the quote from Ali above, this
violates the basic rules of ranges, rules which the vast majority
of code expects ranges to follow.
Also, these rules cannot (and shouldn't) be loosened because
there is no way to check this violation at compile-time. Unless
we ask people to add yet another enum to their ranges and have
even more static-if's in their code. I don't see how benefit to
breaking these rules is greater than the cost.
However, Joseph Wakeling pointed out[1] the generate range[2]:
auto r = generate(() => ++i);
I never liked generate, it always seemed like a hack, now I see
my opinions have been validated.
But unlike map, there isn't a way to make generate work as a
proper range, because as Joe pointed out, popFront does
nothing, front does all the work that popFront would do.
For example, generate.popFrontN does nothing. generate.drop
does nothing. And of course, calling front multiple times does
not yield the same answer, unless you provide a lambda that
does the same thing every time (a useless case).
These are some pretty bad bugs. It's clear to me than generate
should not return a range, but an opApply iterable.