User defined type and foreach

Mike Parker aldacron at gmail.com
Fri Nov 17 07:40:35 UTC 2017


On Friday, 17 November 2017 at 03:15:12 UTC, Tony wrote:

>
> Thanks T! Good information, especially "iterating over a range 
> is supposed to consume it". I have been reading 
> dlang.org->Documentation->Language Reference, but  should have 
> also read dlang.org->Dlang-Tour->Ranges. Although that page

You might also find use in this article (poorly adapted from 
Chapter 6 of Learning D by the publisher, but still readable):

https://www.packtpub.com/books/content/understanding-ranges

> makes a distinction about "range consumption" with regard to a 
> "reference type" or a "value type" and it isn't clear to me why 
> there would be a difference.

With a value type, you're consuming a copy of the original range, 
so you can reuse it after. With a reference type, you're 
consuming the original range and therefore can't reuse it.


========
struct ValRange {
     int[] items;
     bool empty() @property { return items.length == 0; }
     int front() @property { return items[0]; }
     void popFront() { items = items[1 .. $]; }
}

class RefRange {
     int[] items;
     this(int[] src) { items = src; }
     bool empty() @property { return items.length == 0; }
     int front() @property { return items[0]; }
     void popFront() { items = items[1 .. $]; }
}

void main() {
     import std.stdio;

     int[] ints = [1, 2, 3];
     auto valRange = ValRange(ints);

     writeln("Val 1st Run:");
     foreach(i; valRange) writeln(i);
     assert(!valRange.empty);

     writeln("Val 2nd Run:");
     foreach(i; valRange) writeln(i);
     assert(!valRange.empty);

     auto refRange = new RefRange(ints);

     writeln("Ref 1st Run:");
     foreach(i; refRange) writeln(i);
     assert(refRange.empty);

     writeln("Ref 2nd Run:");
     foreach(i; refRange) writeln(i); // prints nothing
}


More information about the Digitalmars-d-learn mailing list