www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Last element of a forward range

reply "bearophile" <bearophileHUGS lycos.com> writes:
If I have a range like this, how do you find its last item using 
Phobos?

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. But do you know if there is a function to do in Phobos? And 
if such function is not present (walkBack? backWalk?) is it a 
good idea to add it to Phobos?


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;
}


Bye,
bearophile
Apr 11 2014
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 11 Apr 2014 21:05:26 -0400, bearophile <bearophileHUGS lycos.com>  
wrote:

 If I have a range like this, how do you find its last item using Phobos?

 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. But do you  
 know if there is a function to do in Phobos? And if such function is not  
 present (walkBack? backWalk?) is it a good idea to add it to Phobos?
Interesting problem. Given that it is a forward range, a zip between it and a saved copy that is advanced by one may work. -Steve
Apr 11 2014
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Steven Schveighoffer:

 Interesting problem.
And it's not an academic one, I have already faced it two or three times :-)
 Given that it is a forward range, a zip between it and a saved 
 copy that is advanced by one may work.
This compiles and gives the expected output, but how do you extract the last item with this? seq.zip(seq.dropOne).writeln; I have written I've added an ER to Phobos with some preliminary code: https://issues.dlang.org/show_bug.cgi?id=12564 Bye, bearophile
Apr 12 2014
parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Saturday, 12 April 2014 at 10:27:00 UTC, bearophile wrote:
 Steven Schveighoffer:

 Interesting problem.
And it's not an academic one, I have already faced it two or three times :-)
 Given that it is a forward range, a zip between it and a saved 
 copy that is advanced by one may work.
This compiles and gives the expected output, but how do you extract the last item with this? seq.zip(seq.dropOne).writeln;
For starters, you can't in the sense that writeln takes by value, and your zip has value semantics. So in fact, it is still unchanged. BTW: That UFCS "seq.zip(someOtherRange)": Ew. So you'd need to start with a: auto z = zip(seq, seq.dropOne); while (!z.empty) z.popFront(); That's step one. Step two would be actually extracting the remainaing range. In theory, you can't. In practice, you can hack around the implementation by: zip.ranges[1].front; Turns out "ranges" is not private. I wouldn't use this. The second, is modifying the stopping policy on the fly: zip.stoppingPolicy = StoppingPolicy.longest; auto a = zip.front[1]; I think both are *very* hackish. I'd do this: auto bck = seq.save; seq.popFront(); while (!seq.empty) { bck.popFront(); seq.popFront(); } auto last = bck.front;
Apr 12 2014