www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 19587] New: std.range.generate's range calls its argument one

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).

--
Jan 15 2019