Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Changeset 1714

Show
Ignore:
Timestamp:
07/04/10 21:04:48 (14 years ago)
Author:
andrei
Message:

Unlisted bug in Map.save and a few stylistic changes

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/phobos/std/algorithm.d

    r1712 r1714  
    4646module std.algorithm; 
    4747 
    4848import std.c.string; 
    4949import std.array, std.container, std.contracts, std.conv, std.date, 
    5050    std.functional, std.math, std.metastrings, std.range, std.string, 
    5151    std.traits, std.typecons, std.typetuple; 
    5252 
    5353version(unittest) 
    5454{ 
    5555    import std.random, std.stdio, std.string; 
    56  
    5756    mixin(dummyRanges); 
    5857} 
    5958 
    6059/** 
    6160Implements the homonym function (also known as $(D transform)) present 
    6261in many languages of functional flavor. The call $(D map!(fun)(range)) 
    6362returns a range of which elements are obtained by applying $(D fun(x)) 
    6463left to right for all $(D x) in $(D range). The original ranges are 
    6564not changed. Evaluation is done lazily. The range returned by $(D map) 
    6665caches the last value such that evaluating $(D front) multiple times 
     
    111110        } 
    112111    } 
    113112} 
    114113 
    115114struct Map(alias fun, Range) if (isInputRange!(Range)) 
    116115{ 
    117116    alias typeof(fun(.ElementType!(Range).init)) ElementType; 
    118117    Range _input; 
    119118    ElementType _cache; 
    120119 
    121     static if(isBidirectionalRange!(Range)) { 
     120    static if (isBidirectionalRange!(Range)) { 
    122121    // Using a second cache would lead to at least 1 extra function evaluation 
    123122    // and wasted space when 99% of the time this range will only be iterated 
    124123    // over in the forward direction.  Use a bool to determine whether cache 
    125124    // is front or back instead. 
    126         bool cacheIsBack
     125        bool cacheIsBack_
    127126 
    128127        private void fillCacheBack() { 
    129128            if (!_input.empty) _cache = fun(_input.back); 
    130             cacheIsBack = true; 
     129            cacheIsBack_ = true; 
    131130        } 
    132131 
    133132        @property ElementType back() { 
    134             if(!cacheIsBack) { 
     133            if (!cacheIsBack_) { 
    135134                fillCacheBack(); 
    136135            } 
    137136            return _cache; 
    138137        } 
    139138 
    140139        void popBack() { 
    141140            _input.popBack; 
    142141            fillCacheBack(); 
    143142        } 
    144143    } 
    145144 
    146145    private void fillCache() { 
    147146        if (!_input.empty) _cache = fun(_input.front); 
    148147 
    149148        static if(isBidirectionalRange!(Range)) { 
    150             cacheIsBack = false; 
     149            cacheIsBack_ = false; 
    151150        } 
    152151    } 
    153152 
    154153    this(Range input) { 
    155154        _input = input; 
    156155        fillCache; 
    157156    } 
    158157 
    159     static if(isInfinite!Range) { 
     158    static if (isInfinite!Range) { 
    160159        // Propagate infinite-ness. 
    161160        enum bool empty = false; 
    162161    } else { 
    163162        @property bool empty() { 
    164163            return _input.empty; 
    165164        } 
    166165    } 
    167166 
    168167    void popFront() { 
    169168        _input.popFront; 
    170         fillCache
     169        fillCache()
    171170    } 
    172171 
    173172    @property ElementType front() { 
    174         static if(isBidirectionalRange!(Range)) { 
    175             if(cacheIsBack) { 
     173        static if (isBidirectionalRange!(Range)) { 
     174            if (cacheIsBack_) { 
    176175                fillCache(); 
    177176            } 
    178177        } 
    179178        return _cache; 
    180179    } 
    181180 
    182     static if(isRandomAccessRange!Range) { 
     181    static if (isRandomAccessRange!Range) { 
    183182        ElementType opIndex(size_t index) { 
    184183            return fun(_input[index]); 
    185184        } 
    186185    } 
    187186 
    188187    // hasLength is busted, Bug 2873 
    189     static if(is(typeof(_input.length) : size_t) 
     188    static if (is(typeof(_input.length) : size_t) 
    190189        || is(typeof(_input.length()) : size_t)) { 
    191190        @property size_t length() { 
    192191            return _input.length; 
    193192        } 
    194193    } 
    195194 
    196     static if(hasSlicing!(Range)) { 
     195    static if (hasSlicing!(Range)) { 
    197196        typeof(this) opSlice(size_t lowerBound, size_t upperBound) { 
    198197            return typeof(this)(_input[lowerBound..upperBound]); 
    199198        } 
    200199    } 
    201200 
    202201    static if (isForwardRange!Range) 
    203202        @property Map save() 
    204203        { 
    205             Map result; 
    206             result._input = _input.save; 
    207             result._cache = _cache; 
    208             return result; 
     204            return this; 
    209205        } 
    210206} 
    211207 
    212208unittest 
    213209{ 
    214210    scope(failure) writeln("Unittest failed at line ", __LINE__); 
    215211    int[] arr1 = [ 1, 2, 3, 4 ]; 
    216212    int[] arr2 = [ 5, 6 ]; 
    217213    auto squares = map!("a * a")(arr1); 
    218214    assert(equal(squares, [ 1, 4, 9, 16 ][])); 
    219215    assert(equal(map!("a * a")(chain(arr1, arr2)), [ 1, 4, 9, 16, 25, 36 ][])); 
    220216 
    221217    // Test the caching stuff. 
    222     auto squares2 = squares; 
     218    assert(squares.back == 16); 
     219    auto squares2 = squares.save; 
    223220    assert(squares2.back == 16); 
     221 
    224222    assert(squares2.front == 1); 
    225223    squares2.popFront; 
    226224    assert(squares2.front == 4); 
    227225    squares2.popBack; 
    228226    assert(squares2.front == 4); 
    229227    assert(squares2.back == 9); 
    230228 
    231229    assert(equal(map!("a * a")(chain(arr1, arr2)), [ 1, 4, 9, 16, 25, 36 ][])); 
    232230 
    233231    uint i; 
     
    571569            while (!_input.empty && !pred(_input.back)) _input.popBack; 
    572570        } 
    573571 
    574572    } 
    575573 
    576574    ref Filter opSlice() 
    577575    { 
    578576        return this; 
    579577    } 
    580578 
    581     static if(isInfinite!Range) { 
     579    static if (isInfinite!Range) { 
    582580        enum bool empty = false;  // Propagate infiniteness. 
    583581    } else { 
    584582        bool empty() { return _input.empty; } 
    585583    } 
    586584 
    587585    void popFront() 
    588586    { 
    589587        do 
    590588        { 
    591589            _input.popFront; 
     
    603601            do 
    604602            { 
    605603                _input.popBack; 
    606604            } while (!_input.empty && !pred(_input.back)); 
    607605        } 
    608606 
    609607        ElementType!(Range) back() { return _input.back;} 
    610608    } 
    611609 
    612610 
    613     static if(isForwardRange!Range) 
     611    static if (isForwardRange!Range) 
    614612    { 
    615613        @property typeof(this) save() 
    616614        { 
    617615            return typeof(this)(_input.save); 
    618616        } 
    619617    } 
    620618} 
    621619 
    622620unittest 
    623621{ 
     
    638636    auto nums = [0,1,2,3,4]; 
    639637    auto forward = filter!"a % 2 == 0"(nums); 
    640638    assert(equal(retro(forward), [4,2,0][])); // f is a bidirectional range 
    641639 
    642640 
    643641    foreach(DummyType; AllDummyRanges) { 
    644642        DummyType d; 
    645643        auto f = filter!"a & 1"(d); 
    646644        assert(equal(f, [1,3,5,7,9])); 
    647645 
    648         static if(isForwardRange!DummyType) { 
     646        static if (isForwardRange!DummyType) { 
    649647            static assert(isForwardRange!(typeof(f))); 
    650648        } 
    651649 
    652         static if(isBidirectionalRange!DummyType) { 
     650        static if (isBidirectionalRange!DummyType) { 
    653651            static assert(isBidirectionalRange!(typeof(f))); 
    654652            assert(equal(retro(f), [9,7,5,3,1])); 
    655653        } 
    656654    } 
    657655} 
    658656 
    659657// move 
    660658/** 
    661659Moves $(D source) into $(D target) via a destructive 
    662660copy. Specifically: $(UL $(LI If $(D hasAliasing!T) is true (see 
     
    869867 
    870868public: 
    871869    this(Range input, Separator separator) 
    872870    { 
    873871        _input = input; 
    874872        _separator = separator; 
    875873        // computeFront(); 
    876874        // computeBack(); 
    877875    } 
    878876 
    879     static if(isInfinite!Range) 
     877    static if (isInfinite!Range) 
    880878    { 
    881879        enum bool empty = false; 
    882880    } else 
    883881    { 
    884882        @property bool empty() 
    885883        { 
    886884            return _frontLength == _atEnd; 
    887885        } 
    888886    } 
    889887 
     
    10041002        _separator = separator; 
    10051003    } 
    10061004 
    10071005    @property Range front() 
    10081006    { 
    10091007        assert(!empty); 
    10101008        ensureFrontLength; 
    10111009        return _input[0 .. _frontLength]; 
    10121010    } 
    10131011 
    1014     static if(isInfinite!Range) 
     1012    static if (isInfinite!Range) 
    10151013    { 
    10161014        enum bool empty = false;  // Propagate infiniteness 
    10171015    } 
    10181016    else 
    10191017    { 
    10201018        @property bool empty() 
    10211019        { 
    10221020            return _frontLength == size_t.max && _input.empty; 
    10231021        } 
    10241022    } 
     
    11511149        else 
    11521150        { 
    11531151            // Chase first terminator 
    11541152            while (_end < _input.length && !_isTerminator(_input[_end])) 
    11551153            { 
    11561154                ++_end; 
    11571155            } 
    11581156        } 
    11591157    } 
    11601158 
    1161     static if(isInfinite!Range) 
     1159    static if (isInfinite!Range) 
    11621160    { 
    11631161        enum bool empty = false;  // Propagate infiniteness. 
    11641162    } 
    11651163    else 
    11661164    { 
    11671165        @property bool empty() 
    11681166        { 
    11691167            return _end == _end.max; 
    11701168        } 
    11711169    } 
     
    12741272        auto last = _input.front; 
    12751273        do 
    12761274        { 
    12771275            _input.popFront; 
    12781276        } 
    12791277        while (!_input.empty && binaryFun!(pred)(last, _input.front)); 
    12801278    } 
    12811279 
    12821280    @property ElementType!(R) front() { return _input.front; } 
    12831281 
    1284     static if(isBidirectionalRange!R) 
     1282    static if (isBidirectionalRange!R) 
    12851283    { 
    12861284        void popBack() 
    12871285        { 
    12881286            auto last = _input.back; 
    12891287            do 
    12901288            { 
    12911289                _input.popBack; 
    12921290            } 
    12931291            while (!_input.empty && binaryFun!(pred)(last, _input.back)); 
    12941292        } 
    12951293 
    12961294        @property ElementType!(R) back() { return _input.back; } 
    12971295    } 
    12981296 
    1299     static if(isInfinite!R) 
     1297    static if (isInfinite!R) 
    13001298    { 
    13011299        enum bool empty = false;  // Propagate infiniteness. 
    13021300    } 
    13031301    else 
    13041302    { 
    13051303        @property bool empty() { return _input.empty; } 
    13061304    } 
    13071305 
    13081306 
    1309     static if(isForwardRange!R) { 
     1307    static if (isForwardRange!R) { 
    13101308        @property typeof(this) save() { 
    13111309            return typeof(this)(_input.save); 
    13121310        } 
    13131311    } 
    13141312} 
    13151313 
    13161314/// Ditto 
    13171315Uniq!(pred, Range) uniq(alias pred = "a == b", Range)(Range r) 
    13181316{ 
    13191317    return typeof(return)(r); 
     
    13261324    assert(equal(r, [ 1, 2, 3, 4, 5 ][])); 
    13271325    assert(equal(retro(r), retro([ 1, 2, 3, 4, 5 ][]))); 
    13281326 
    13291327    foreach(DummyType; AllDummyRanges) { 
    13301328        DummyType d; 
    13311329        auto u = uniq(d); 
    13321330        assert(equal(u, [1,2,3,4,5,6,7,8,9,10])); 
    13331331 
    13341332        static assert(d.rt == RangeType.Input || isForwardRange!(typeof(u))); 
    13351333 
    1336         static if(d.rt >= RangeType.Bidirectional) { 
     1334        static if (d.rt >= RangeType.Bidirectional) { 
    13371335            assert(equal(retro(u), [10,9,8,7,6,5,4,3,2,1])); 
    13381336        } 
    13391337    } 
    13401338} 
    13411339 
    13421340// group 
    13431341/** 
    13441342Similarly to $(D uniq), $(D group) iterates unique consecutive 
    13451343elements of the given range. The element type is $(D 
    13461344Tuple!(ElementType!R, uint)) because it includes the count of 
     
    13801378            _current = tuple(_input.front, 1u); 
    13811379            _input.popFront; 
    13821380            while (!_input.empty && comp(_current.field[0], _input.front)) 
    13831381            { 
    13841382                ++_current.field[1]; 
    13851383                _input.popFront; 
    13861384            } 
    13871385        } 
    13881386    } 
    13891387 
    1390     static if(isInfinite!R) 
     1388    static if (isInfinite!R) 
    13911389    { 
    13921390        enum bool empty = false;  // Propagate infiniteness. 
    13931391    } 
    13941392    else 
    13951393    { 
    13961394        @property bool empty() 
    13971395        { 
    13981396            return _current.field[1] == 0; 
    13991397        } 
    14001398    } 
    14011399 
    14021400    @property ref Tuple!(ElementType!R, uint) front() 
    14031401    { 
    14041402        assert(!empty); 
    14051403        return _current; 
    14061404    } 
    14071405 
    1408     static if(isForwardRange!R) { 
     1406    static if (isForwardRange!R) { 
    14091407        @property typeof(this) save() { 
    14101408            typeof(this) ret; 
    14111409            ret._input = this._input.save; 
    14121410            ret._current = this._current; 
    14131411 
    14141412            return ret; 
    14151413        } 
    14161414    } 
    14171415} 
    14181416