Can't recreate a range?
Paul Backus
snarwin at gmail.com
Thu Apr 30 22:39:36 UTC 2020
On Thursday, 30 April 2020 at 18:30:14 UTC, H. S. Teoh wrote:
> On Thu, Apr 30, 2020 at 06:05:55PM +0000, Paul Backus via
> Digitalmars-d-learn wrote: [...]
>> Doing work in popFront instead of front is usually an
>> anti-pattern, since it forces eager evaluation of the next
>> element even when that element is never used. You should only
>> do this if there's no reasonable way to avoid it.
>
> Really?? IME, usually you *need* to do work in popFront instead
> of front, because otherwise .empty wouldn't be able to tell
> whether there is another element or not. E.g., in filtering a
> range based on some criterion on each element, you can't defer
> computing the next element until .front because you can't
> predict whether there will be another element that won't be
> dropped by popFront.
There are certainly cases where it can't be avoided. Filter is
one; file I/O (as Steven Schveighoffer pointed out) is another
one. Obviously, you gotta do what you gotta do. Still, I think
that as long as work *can* be deferred to .front, it should be.
That's the essence of lazy evaluation: only do your computation
once you're absolutely sure it's necessary.
> 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.
More information about the Digitalmars-d-learn
mailing list