[Issue 12564] New: std.range.backWalk, std.range.backWalkMaybe
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Sat Apr 12 03:25:59 PDT 2014
https://issues.dlang.org/show_bug.cgi?id=12564
Issue ID: 12564
Summary: std.range.backWalk, std.range.backWalkMaybe
Product: D
Version: D2
Hardware: All
OS: All
Status: NEW
Severity: enhancement
Priority: P1
Component: Phobos
Assignee: nobody at puremagic.com
Reporter: bearophile_hugs at eml.cc
If I have a range like this, how do you find its last item using Phobos? This
is a problem I have had to solve few times. A simple way is to use
seq.array.back, but this wastes memory. Another simple way is to use a foreach
loop keeping the last seen:
void main() {
import std.stdio, std.algorithm, std.range;
int m = 75;
auto seq = recurrence!q{ a[n - 1] + a[n - 2] }(1, 1)
.until!(x => x > m)(OpenRight.no);
seq.array.back.writeln; // 89
//seq.back.writeln;
auto last = -1;
foreach (immutable x; seq)
last = x;
last.writeln;
}
But I'd like a function to do it nicely in UFCS chains too. So I suggest to add
functions like this (the code here is illustrative, it doesn't work in all
cases):
import std.stdio, std.algorithm, std.range, std.traits,
std.typecons;
// Throws when sequence is empty.
ElementType!R backWalk(R)(R sequence)
if (isForwardRange!R) {
if (sequence.empty)
throw new Exception("backWalk: empty imput");
static if (__traits(compiles, { sequence.back; })) {
return sequence.back;
} else {
ElementType!R last;
foreach (x; sequence)
last = x;
return last;
}
}
// Returns a given default element when sequence is empty,
// and can be nothrow.
ElementType!R backWalk(R, T)(R sequence, T defaultResult)
if (isForwardRange!R && is(T == ElementType!R)) {
if (sequence.empty)
return defaultResult;
static if (__traits(compiles, { sequence.back; })) {
return sequence.back;
} else {
ElementType!R last;
foreach (x; sequence)
last = x;
return last;
}
}
// Returns a Nullable when sequence is empty,
// and can be nothrow.
Nullable!(ElementType!R) backWalkMaybe(R)(R sequence)
if (isForwardRange!R) {
if (sequence.empty)
return typeof(return)();
static if (__traits(compiles, { sequence.back; })) {
return typeof(return)(sequence.back);
} else {
typeof(return) last;
foreach (x; sequence)
last = typeof(return)(x);
return last;
}
}
void main() { // Some tests and examples.
int m = 75;
auto seq = recurrence!q{ a[n - 1] + a[n - 2] }(1, 1)
.until!(x => x > m)(OpenRight.no);
seq.array.back.writeln; // 89
//seq.back.writeln; // Not possible.
seq.backWalk.writeln;
[1, 2].backWalk.writeln;
seq.backWalkMaybe.writeln;
[1, 2].backWalkMaybe.writeln;
"ABC".backWalk.writeln;
"ABC".backWalkMaybe.writeln;
"".backWalk(dchar('a')).writeln;
const c = 'a';
//"".backWalk(c).writeln; // This too should work.
}
--
More information about the Digitalmars-d-bugs
mailing list