On 4/30/20 2:30 PM, 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.
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.
Even when the range involves some expensive per-element computation, I
find that it's simpler to just compute and cache in .popFront instead of
adding extra baggage to .front to know when the computation has already
been performed.
I'm hard-pressed to come up with an example where deferring computation
to .front is a good idea!
There could be expensive operations done to construct the element that
aren't necessary to iterate the range, but generally you achieve this by
using something like map and cache.
But really the only valid use case for this is if you create a range but
never use it. Some may need this, but I think a wrapper would be a
better solution than enforcing a certain usage pattern.
-Steve