Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std.range.generate's range calls its argument one time too many #10366

Open
dlangBugzillaToGithub opened this issue Jan 15, 2019 · 3 comments
Open

Comments

@dlangBugzillaToGithub
Copy link

snarwin+bugzilla (@pbackus) reported this on 2019-01-15T21:59:11Z

Transfered from https://issues.dlang.org/show_bug.cgi?id=19587

CC List

  • dkorpel
  • remi.thebault

Description

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).
@dlangBugzillaToGithub
Copy link
Author

dkorpel commented on 2021-05-06T22:53:27Z

Just got hit by this today, my `generate!(() => readln()).take(10).array` discarded the line after the 10 lines put into the array.

This is really annoying, but changing this would be a breaking change, so I'm afraid the fix would be either:

- a template parameter 'caching' with default value of `true`
- a new synonym symbol, similar to `approxEqual => isClose`, with the possibility to deprecate the old symbol (caching can still be achieved by doing `generate!(f).cache`). I'm not sure what that synonym would be, things that come to mind are `generateLazy`, `successiveCalls`, `repeatEvaluate`, but I'm not a big fan of them.

@dlangBugzillaToGithub
Copy link
Author

remi.thebault commented on 2022-05-06T16:50:40Z

*** Issue 23094 has been marked as a duplicate of this issue. ***

@dlangBugzillaToGithub
Copy link
Author

dlang-bot commented on 2022-05-06T17:37:06Z

@rtbo created dlang/phobos pull request #8453 "fix issue 19587" fixing this issue:

- fix issue 19587
  
  avoid that std.range.generate calls
  fun one time too many

https://github.com/dlang/phobos/pull/8453

@LightBender LightBender removed the P4 label Dec 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants