Comment #0 by philippe.sigaud — 2010-03-04T05:56:05Z
std.algorithm.filter returns a forward range. This could become a bidirectional range if its input range is also a bidirectional range. That way, filter can fed to more algorithms.
Obviously, it cannot in general become a random-access range or define a length... Too bad.
Possible code follow:
struct Filter(alias pred, Range) if (isInputRange!(Range))
{
Range _input;
this(Range r)
{
_input = r;
while (!_input.empty && !pred(_input.front)) _input.popFront;
static if (isBidirectionalRange!Range)
while (!_input.empty && !pred(_input.back)) _input.popBack;
}
ref Filter opSlice()
{
return this;
}
bool empty() { return _input.empty; }
void popFront()
{
do
{
_input.popFront;
} while (!_input.empty && !pred(_input.front));
}
ElementType!(Range) front() { return _input.front;}
static if (isBidirectionalRange!Range) {
void popBack()
{
do
{
_input.popBack;
} while (!_input.empty && !pred(_input.back));
}
ElementType!(Range) back() { return _input.back;}
}
}
unittest
{
auto r = [0,1,2,3,4];
auto f = filter!"a%2==0"(r);
assert(equal(retro(f), [4,2,0][])); // f is a bidirectional range
}
Comment #1 by dsimcha — 2010-06-30T19:58:43Z
Fixed SVN.
Comment #2 by default_357-line — 2023-03-09T07:48:29Z
Got unfixed at some point:
```
import std.algorithm : filter;
import std.range : only;
void main()
{
int[] a = [2, 3];
assert(only(2, 3).back == 3);
assert(a.filter!"a == 2".back == 2);
}
```
=>
onlineapp.d(7): Error: no property `back` for `filter(a)` of type `std.algorithm.iteration.FilterResult!(unaryFun, int[])`
Apparently there's `filterBidirectional`. I am violently opposed to that function and all it represents. `filter` should support bidirectional iteration by default, with maybe `filterUnidirectional` or `forceForwardRange` if you want to *disable* it. Since when do we sacrifice functionality for speed by default?
Comment #3 by robert.schadek — 2024-12-01T16:13:19Z