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
}

Reply via email to