Dealing with ranges where front and popFront do the same logic / eager ranges

Dennis dkorpel at gmail.com
Tue Oct 16 22:59:50 UTC 2018


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.


More information about the Digitalmars-d-learn mailing list