Can't recreate a range?

Steven Schveighoffer schveiguy at gmail.com
Fri May 1 03:44:26 UTC 2020


On 4/30/20 6:39 PM, Paul Backus wrote:
> On Thursday, 30 April 2020 at 18:30:14 UTC, H. S. Teoh wrote:
>> Also, for ranges based on generator functions, if .front is lazy then 
>> you need to keep extra baggage around your range to indicate whether 
>> or not the generator has been invoked yet; it's easier to just always 
>> compute the next element eagerly and cache it, and .front just returns 
>> the cached data.
> 
> std.range.generate is actually a perfect example of the problem with 
> doing work in popFront. Because it has to call popFront both on 
> construction *and* after every element, consuming n elements will call 
> the generator function n+1 times. The final call is completely wasted.

generate used to do everything on front. But that meant it wasn't a true 
range as multiple calls to front generated different data (popFront was 
a noop). I fixed it a while ago.

It should be the status quo to do all work in popFront, and then you 
should wrap if you need different behavior.

I'm ok with something like this (I'm kind of surprised something like 
this doesn't exist already):

struct LazyRange(R)
{
    R src;
    bool frontEvaluated;
    void sync() {
        if(!frontEvaluated) {
           src.popFront;
           frontEvaluated = true;
        }
    }
    auto front() {
        sync();
        return src.front;
    }
    bool empty() {
        sync();
        return src.empty;
    }
    void popFront() {
        sync();
        frontEvaluated = false;
    }
}

-Steve


More information about the Digitalmars-d-learn mailing list