Fix 12564, 14493: add std.range.walkBack to get the last element of an input range#5153
Fix 12564, 14493: add std.range.walkBack to get the last element of an input range#5153wilzbach wants to merge 1 commit intodlang:masterfrom
Conversation
8171388 to
d4e066b
Compare
d4e066b to
b6f083c
Compare
| if ((isInputRange!Range || isIterable!Range) && !isInfinite!Range) | ||
| in | ||
| { | ||
|
|
There was a problem hiding this comment.
It would be good to provide another overload which accepts a fallback value returned when the input is empty rather than causing an error
There was a problem hiding this comment.
There are at least these options:
- use Nullable
- provide an (
.ifEmpty(value)) method that will yield a range of length 1 with the default value if an empty range is passed in and the otherwise the range unmodified - use
enforceinstead (generally disliked, because exceptions allocate) - provide an overload with a
seed
The best precedent I found is maxElement, so I guess we should follow this then.
There was a problem hiding this comment.
See #5154 for further discussion about handling empty ranges.
| { | ||
| // Rebindable doesn't support all types as of now | ||
| Unqual!(ElementType!Range) last; | ||
| foreach (e; range) |
There was a problem hiding this comment.
This can be done without Unqual or Rebindable.
while(!range.empty){
auto element = range.front;
range.popFront();
if(range.empty) return element;
}There was a problem hiding this comment.
Yeah, but unfortunately that is slower:
> ldc -O5 -release -boundscheck=off walkBack.d && ./walkBack
walkBack.foreach = 3 secs, 772 ms, 463 μs, and 6 hnsecs
walkBack.while = 4 secs, 191 ms, 417 μs, and 8 hnsecs
There was a problem hiding this comment.
I'm having issues testing using your code with DMD. As it was, the first while test was consuming the range and subsequent tests failed because the range had been consumed.
I fixed it by preceding each call with auto r = range; and operating on r instead, but this served only to make the while approach dramatically slower while not significantly affecting the performance of the foreach test.
I would've expected that rewriting like so might make their performance more similar, but I'm surprised the compiler wasn't able to optimize the structure to look more like this anyway:
bool empty = range.empty;
while(!empty){
auto element = range.front;
range.popFront();
empty = range.empty;
if(empty) return element;
}@UplinkCoder can you explain what's going on here?
There was a problem hiding this comment.
the foreachloop should be rewritten to this:
{
typeof(range.front()) elm = range.front;
while(!range.empty)
{
ForeachBody()
range.popFront();
elm = range.front;
}
}
There was a problem hiding this comment.
Rather this:
{
while(!range.empty)
{
typeof(range.front()) elm = range.front;
ForeachBody()
range.popFront();
}
}
DmitryOlshansky
left a comment
There was a problem hiding this comment.
Truth be told all of these new names to fill every minor need make my head spin. What's the semantics of something like walkBack - I can't tell at glance.
Yeah, and while this probably is something that folks need occasionally, it doesn't seem like all that great an idea in general given how horribly inefficient it is. As such, if we were to add it, I'd be tempted to argue that something descriptive and ugly like But as the second linked bug report mentions, |
The idea behind the
If this functionality be added, I would argue to stay in the naming scheme as
Two random points:
input.buffer(5).tail(5); |
Oh, now I get it so this is like walkLength. I initially read walkBack as an imperative which sounds more like walk the range backwards. Still sucks I guess as I'd never reach out for that intuitively.
By the same person who absolutely loves filling enhancement requests, sometimes it seems to me that we often overlook an option of WONTFIX. |
…nt of an input range
b6f083c to
787ad9b
Compare
|
Knee-jerk reaction: how does this compare to |
See above for a longer motivation, but in short like |
|
Understood. So we have a range that is input but not forward, and want to advance it through the end to get the last element. What's wrong with |
Nothing - I am closing this and the existing bugs I found as |
|
@wilzbach yes awesome and actually that's a rather clever (ahem) use of |
Sure -> #5227 |
This seems to be a missing functionality (when I bumped into this I found two open issues). It behaves as
walkLength.It got a bit messy because
Rebindableisn't a thing yet (see #4363 for more details).