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