On Wed, 16 Feb 2011 14:24:36 -0500, Andrej Mitrovic
<andrej.mitrov...@gmail.com> wrote:
The only thing I could come up with is exhausting the entire range to
get the length of a bidirectional range. But that's inefficient.
Anyway here's the dull thing:
import std.stdio;
import std.range;
import std.array;
R findBack(alias pred = "a == b", R, E)(R haystack, E needle)
if (isBidirectionalRange!R)
{
size_t index;
bool found;
auto saved = haystack;
foreach (item; retro(haystack))
{
if (item == needle)
{
found = true;
index++;
break;
}
index++;
}
if (found)
{
size_t newIndex;
while (!haystack.empty)
{
newIndex++;
haystack.popBack;
}
newIndex -= index;
while (!saved.empty && newIndex)
{
saved.popFront;
newIndex--;
}
}
return saved;
}
void main()
{
auto orig = [4, 0, 4, 0];
auto result = findBack(orig, 4);
assert(array(result) == [4, 0]);
result.front = 10;
assert(orig == [4, 0, 10, 0]);
}
You'll have to forgive me but I have yet to study algorithms properly. :)
Hehe if you are willing to traverse the whole range, it's much easier than
this:
auto saved = R.init;
while(!haystack.empty)
{
if(haystack.front == needle)
saved = haystack.save();
haystack.popFront();
}
return saved;
The point is, no matter what you do, the missing ability to construct a
range from two iterators/cursors means you must degrade performance to get
the desired effect.
This might be able to be simulated with having a range "flip" itself based
on certain criteria, but it must be a range-supported feature, which means
more complexity goes into the range concept.
-Steve