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.

Reply via email to