January 15, 2019
https://issues.dlang.org/show_bug.cgi?id=19587

          Issue ID: 19587
           Summary: std.range.generate's range calls its argument one time
                    too many
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Linux
            Status: NEW
          Severity: enhancement
          Priority: P1
         Component: phobos
          Assignee: nobody@puremagic.com
          Reporter: snarwin+bugzilla@gmail.com

Example:

---
int count = 0;

int counter()
{
    return count++;
}

void main()
{
    import std.algorithm;
    import std.range;
    import std.stdio;

    auto gen = generate!counter;
    gen.take(3).each!writeln;
    assert(count == 3); // fails, count == 4
}
---

This behavior leads to two related problems:

1) Ranges, in general, are expected to be lazy. Eagerly calling the generator function on construction and in popFront violates that expectation.

2) As a result, writing optimal code using ranges created with `generate` (that is, code which does no unnecessary work) requires special-case handling, since Phobos' algorithms (for example, `take`, above) "naively" assume that construction and popFront are cheap.

These problems are especially bothersome when the generator function is expensive to call (for example, if it accesses the network).

--