www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 3871] New: std.algorithm.map should propagate its input range properties

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3871

           Summary: std.algorithm.map should propagate its input range
                    properties
           Product: D
           Version: 2.040
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: Phobos
        AssignedTo: nobody puremagic.com
        ReportedBy: philippe.sigaud gmail.com



14:51:21 CET ---
Looking at std.algorithm.map in Phobos for 2.040, it's a forward range. It
could easily be enhanced by propagating more of its input range properties:

- becoming bidirectional if its input is bidir
- the same for random-access
- the same for an infinite range
- for slicing
- and defining a .length member if input has one.

That way, map can be used more transparently as an intermediate step in
building ranges upon ranges.

Here is some possible code for this improvement:


struct Map(alias fun, Range) if (isInputRange!(Range))
{
    alias typeof(fun(.ElementType!(Range).init)) ElementType;
    Range _input;
    ElementType _cache, _backCache;

    private void fillCache() { if (!_input.empty) _cache = fun(_input.front); }
    static if (isBidirectionalRange!Range) {
        private void fillBackCache() { if (!_input.empty) _backCache =
fun(_input.back);}
    }

    this(Range input) {
        _input = input; fillCache;
        static if (isBidirectionalRange!Range) fillBackCache;
    }
    static if (isInfinite!Range) {
        enum bool empty = false; // infinite also
    }
    else  {
        bool empty() { return _input.empty; }
    }
    void popFront() { _input.popFront; fillCache; }
    ElementType front() { return _cache; }

    static if (isBidirectionalRange!Range) {
        void popBack() { _input.popBack; fillBackCache; }
        ElementType back() { return _backCache; }
    }

    static if (hasLength!Range)
        size_t length() { return _input.length;}

    static if (isRandomAccessRange!Range)
        ElementType opIndex(size_t i) { return fun(_input[i]);}

    static if (hasSlicing!Range) {
        Map!(fun, Range) opSlice(size_t i1, size_t i2) {
            return map!fun(_input[i1..i2]);
        }
    }

    typeof(this) opSlice() {
        return this;
    }
}

unittest
{
    auto r = [0,1,2,3,4]; // random-access range with a length and slicing.
    auto m = map!"a*a"(r);

    assert(equal(retro(m), [16,9,4,1,0][])); // bidirectional range
    assert(m[3] == 9); // random-access range
    assert(m.length == 5); // length
    assert(equal(m[1..3], [1,4][])); // slicing

    auto m2 = map!"a*a"(cycle(r)); // cycle(r) is infinite
    assert(isInfinite!(typeof(m2))); // m2 is infinite also.
    assert(!is(m2.length)); // cycle(r) doesn't have a length, so neither has
m2.
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 04 2010
parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3871


David Simcha <dsimcha yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |dsimcha yahoo.com
         Resolution|                            |DUPLICATE



*** This issue has been marked as a duplicate of issue 2872 ***

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jun 17 2010