digitalmars.D.bugs - [Issue 12564] New: std.range.backWalk, std.range.backWalkMaybe
- d-bugmail puremagic.com (95/95) Apr 12 2014 https://issues.dlang.org/show_bug.cgi?id=12564
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 puremagic.com Reporter: bearophile_hugs 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. } --
Apr 12 2014