I've always been curious around the design choice of ranges to
make front and popFront separate functions, instead of having
popFront return the front. I suppose it is useful sometimes to be
able to access front multiple times without having to save it
temporarily (can't think of a specific example though).
But sometimes doing popFront requires doing the same work as
front. For example, for strings and autodecoding, both front and
popFront need to determine the length of the next code point. Now
for utf-8 that is still managable, but I'm making a tokenizer
range for a programming language. Most of the logic in `front`
needs to be duplicated for `popFront`! (and `empty` as well)
So I often end up with designs like:
```
struct Range
{
string source;
bool empty;
Token front;
this(string source) {
this.source = source;
popFront();
}
void popFront() {
// *complicated logic*
front = result;
}
}
```
This increases the size of the Range struct, and makes the range
one element eager. If the first token is invalid, and I use
Exceptions, then merely constructing the range will immediately
throw an Exception. I recall reading that constructors throwing
exceptions are problematic, but I don't have any experience with
that. So maybe I should add a try-catch in the constructor, and
rethrow the Exception upon the first 'front' call? That feels
hacky.
This is not a dealbreaker, I'm just curious on your tips and
opinions regarding this.