On Wednesday, 25 January 2017 at 16:15:49 UTC, Las wrote:
So the reference says that (when range has the properties) `foreach (e; range) { ... }` is equivalent to:
for (auto __r = range; !__r.empty; __r.popFront())
{
    auto e = __r.front;
    ...
}

Though this isn't always true, as when I use this struct:
struct S {
        int front = 10;
        void popFront() {
                --front;
        }
        @property bool empty() {
                return front == 0;
        }
}

then I can do this:
void main() {
        S s;
        auto p = &s;
        p.popFront;
        writeln(p.front);
}

But not this:
void main() {
        S s;
        auto p = &s;
        foreach(i; p)
                writeln(i);
}

x.d(18): Error: invalid foreach aggregate p
Failed: ["dmd", "-v", "-c", "-of/tmp/.rdmd-1000/rdmd-x.d-032B33C4A922C519594F67AF08DBF6C9/objs/x.o", "x.d", "-I."]

Why should this work? Because some times I want foreach to modify the iterator, because some times I like to have an inner foreach that uses the same iterator as the outer one, to effectively still iterate over the same range, but change the contents of the loop.

Bad example:
foreach(i; &range) {
  writeln(i);
  if(i > 2) foreach(i; &range) {
    writeln(i * 3);
    if(i < 10)
      break;
  }
}

This loop would change behavior each time one of the 'if's pass.

An alternative would be to implement a new foreach, perhaps &foreach, that does this instead: for (/+ NB: We are not copying the range! +/; !range.empty; range.popFront())
{
    auto e = range.front;
    ...
}

Related:
UFCS does not work on pointers, which matters because of std.range.primitives.

Thoughts?

Not sure if this is a bug in isInputRange or foreach, but they should work consistently. Anyway, another solution is to use refRange:

void main() {
    import std.range : refRange;
    S s;
    auto p = refRange(&s);
    foreach(i; p)
        writeln(i);
}

That way you don't need to dereference 'p' everytime you want to iterate over it. Plus, it should compose well with other range wrappers / algorithms.

Reply via email to