On 3/9/23 11:44 AM, FeepingCreature wrote:
On Thursday, 9 March 2023 at 13:16:07 UTC, Steven Schveighoffer wrote:
On 3/9/23 3:06 AM, FeepingCreature wrote:
Yes I know the stated reason, to save time initializing the range in
You know what I did because we didn't know
I literally walked the entire range returned by
filter to find the last matching element.
retro changes the semantics of the range, which often represents business data. Thinking about the underlying model is complicated enough without throwing in "But consider: what if the elements were in reverse order".
Well, walking the entire range to find the last one doesn't imply that ordering matters at all. You are just looking for the last one.
> > >
filter should expose
back. By all means, let
back lazily initialize, but I don't understand how
filterBidirectional was ever considered acceptable. Since when do we sacrifice ease of use for performance? I mean, since 2011 apparently. - This is bad ergonomics, bad discoverability and bad API design.
filterBidirectional delenda est.
This has been a constant debate -- should ranges be allowed to lazily initialize on the first call to front (or back)?
I'd say no. back/front shouldn't be modifying operations. I dislike the idea of storing a "was initialized" flag and having to check that on every call.
That being said, there's no formal requirement for it. It's just a convention I think Phobos should stick to for its included ranges.
Sure: so precompute both
filter call. No caching. This isn't done right now because the language presumes, arbitrarily, that you won't care about
back. That's what I meant by sacrificing convenience for performance. Just do what
filterBidirectional does, every time, and have the current
filter be the odd one out.
filterForward or whatever.
I would be fine with that. But in truth, this is simply an acceptance of the status quo, just with different names.
(I think the best way to go, in truth, is to preinitialize front and cache back. But that solution, much as I think it is optimal for all involved interests, is very hard to love.)
I prefer to have control over all the capabilities. If there is going to be significant cost for something I won't actually use, I'd rather avoid it.
Allowing composability might be the way to go.
That said, I think the range API has a fundamental problem here.
front on every access, because it reasonably presumes that we will then want to query it. However, it cannot rely on this. If we were guaranteed that every access to
popFront would alternate with at least one access to
front, and conversely
popBack, we could just reduce
nextRange.popBack and do the rest of the popping in
back! Then in the fast case (one access to each, in turn) we would not waste any check. And the actual
filter call would always be constant-time.
empty are semantically non-mutating properties. Calling
empty as many times as you want should not alter any values until you call
I prefer them to be actually non-mutating as well.
Delaying construction seems like the better option, and having such a wrapper solves all those problems for those who want lazy, without imposing on users who are intending to just use a range as it's intended.