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

Changeset 1749

Show
Ignore:
Timestamp:
07/12/10 00:50:32 (14 years ago)
Author:
andrei
Message:

Changed definition of isOutputRange and introduced universal function put(R, E) that puts an element in an output range.

Files:

Legend:

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

    r1741 r1749  
    11// Written in the D programming language. 
    22 
    33/** 
    4 This module defines a few useful _range incarnations. Credit for ideas 
    5 in building this module go to $(WEB fantascienza.net/leonardo/so/, 
    6 Leonardo Maffi). 
     4This module defines a few useful _range incarnations. Credit for some 
     5of the ideas in building this module goes to $(WEB 
     6fantascienza.net/leonardo/so/, Leonardo Maffi). 
    77 
    88Macros: 
    99 
    1010WIKI = Phobos/StdRange 
    1111 
    1212Copyright: Copyright Andrei Alexandrescu 2008-. 
    1313License:   $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 
    1414Authors:   $(WEB erdani.org, Andrei Alexandrescu) 
    1515*/ 
    1616module std.range; 
     
    219219        bool empty(); 
    220220        int front(); 
    221221    } 
    222222    static assert(isInputRange!(B)); 
    223223    static assert(isInputRange!(int[])); 
    224224    static assert(isInputRange!(char[])); 
    225225} 
    226226 
    227227/** 
    228228Returns $(D true) if $(D R) is an output range. An output range can be 
    229 defined in two ways. 
    230  
    231 $(OL $(LI $(D R) might define the primitive $(D put) that accepts an 
    232 object convertible to $(D E). The following code should compile for 
    233 such an output range: 
     229defined in three ways. 
     230 
     231$(OL 
     232 
     233$(LI $(D R) might define the primitive $(D put) that accepts an object 
     234convertible to $(D E). The following code should compile for such an 
     235output range: 
    234236 
    235237---- 
    236238R r; 
    237239E e; 
    238240r.put(e);        // can write an element to the range 
    239241---- 
    240242 
    241243The semantics of $(D r.put(e)) an output range (not checkable during 
    242244compilation) are assumed to output $(D e) to $(D r) and advance to the 
    243245next position in $(D r), such that successive calls to $(D r.put) add 
    244246extra elements to $(D r).) 
    245247 
    246248$(LI An input range with assignable elements is also an output 
    247249range. In that case, inserting elements into the range is effected 
    248250with two primitive calls: $(D r.front = e, r.popFront()). Such a range 
    249 functions for output only as long as it is not empty.)) 
     251functions for output only as long as it is not empty.) 
     252 
     253---- 
     254R r; 
     255E e; 
     256r.front = e;    // can write an element to the range 
     257---- 
     258 
     259$(LI Any $(D function) or $(D delegate) accepting arrays of $(D E) as 
     260input is also a valid output range.)) 
    250261 
    251262To write elements to either kind of output range, call the free 
    252263function $(D put(r, e)) defined below. That function takes the 
    253264appropriate cource of action depending on the range's kind. 
    254265 */ 
    255266template isOutputRange(R, E) 
    256267{ 
    257268    enum bool isOutputRange = is(typeof( 
    258269    { 
    259         R r;            // can define a range object 
     270        R r; 
    260271        E e; 
    261         r.put(e);       // can write element to range 
    262     }())) || isInputRange!R && is(typeof( 
    263     { 
    264         R r;               // can define a range object 
     272        r.put(e);          // can write element to range 
     273    }())) 
     274        || 
     275    isInputRange!R && is(typeof( 
     276    { 
     277        R r; 
    265278        E e; 
    266279        r.front = e;       // can assign to the front of range 
     280    }())) 
     281        || 
     282        is(typeof( 
     283    { 
     284        R r; 
     285        E[] es; 
     286        r(es); 
    267287    }())); 
    268288} 
    269289 
    270290/** 
    271291Outputs $(D e) to $(D r), which must be an output range. Depending on 
    272 the range's kind, it either evaluates $(D r.put(e)) or $(D (r.front = 
    273 e, r.popFront())). 
     292the range's kind, it evaluates one of the following: 
     293 
     294$(OL 
     295 
     296$(LI If $(D R) defines $(D put), then output is effected by evaluating 
     297$(D r.put(e)).) 
     298 
     299$(LI Else if $(D R) is an input range with assignable front, then 
     300output is effected by evaluating $(D (r.front = e, r.popFront())).) 
     301 
     302$(LI Else if $(D R) is a function type, a delegate type, or a type 
     303defining $(D opCall), then output is effected by evaluating $(D 
     304r(e)).) 
    274305 */ 
    275306void put(R, E)(ref R r, E e) if (isOutputRange!(R, E)) 
    276307{ 
    277     static if (is(typeof(&r.put))) 
     308    static if (!isArray!R && is(typeof(r.put(e)))) 
    278309    { 
    279310        r.put(e); 
    280311    } 
    281     else 
     312    else static if (isInputRange!R && is(typeof(r.front = e))) 
    282313    { 
    283314        r.front = e; 
    284315        r.popFront(); 
     316    } 
     317    else static if (isArray!E && is(typeof(r(e)))) 
     318    { 
     319        r(e); 
     320    } 
     321    else static if (is(typeof(r(new E[])))) 
     322    { 
     323        r((&e)[0 .. 1]); 
     324    } 
     325    else 
     326    { 
     327        static assert(false); 
    285328    } 
    286329} 
    287330 
    288331unittest 
    289332{ 
    290333    struct A {} 
    291334    static assert(!isInputRange!(A)); 
    292335    struct B 
    293336    { 
    294337        void put(int); 
    295338    } 
    296339    static assert(isOutputRange!(B, int)); 
    297340    static assert(isOutputRange!(int[], int)); 
     341} 
     342 
     343unittest 
     344{ 
     345    void myprint(in char[] s) { writeln('[', s, ']'); } 
     346    static assert(isOutputRange!(typeof(&myprint), char)); 
    298347} 
    299348 
    300349/** 
    301350Returns $(D true) if $(D R) is a forward range. A forward range is an 
    302351input range that can save "checkpoints" by simply copying it to 
    303352another value of the same type. Notable examples of input ranges that 
    304353are $(I not) forward ranges are file/socket ranges; copying such a 
    305354range will not save the position in the stream, and they most likely 
    306355reuse an internal buffer as the entire stream does not sit in 
    307356memory. Subsequently, advancing either the original or the copy will