D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 3872 - std.algorithm.filter could become bidirectional if its input range is bidir
Summary: std.algorithm.filter could become bidirectional if its input range is bidir
Status: REOPENED
Alias: None
Product: D
Classification: Unclassified
Component: phobos (show other issues)
Version: D2
Hardware: All All
: P2 enhancement
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-03-04 05:56 UTC by Philippe Sigaud
Modified: 2024-12-01 16:13 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Philippe Sigaud 2010-03-04 05:56:05 UTC
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 David Simcha 2010-06-30 19:58:43 UTC
Fixed SVN.
Comment 2 FeepingCreature 2023-03-09 07:48:29 UTC
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 dlangBugzillaToGithub 2024-12-01 16:13:19 UTC
THIS ISSUE HAS BEEN MOVED TO GITHUB

https://github.com/dlang/phobos/issues/9883

DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB