go-functional
go-functional copied to clipboard
[Feature 🔨]: Iterators should not repeatedly call their underlying iterators when exhausted
Is your feature request related to a problem? Please describe.
Iterators often call underlying iterators (such as Map or Filter). Sometimes an iterator can become exhausted before its underlying iterator has been exhausted (e.g. Take). Currently there is nothing defined in documentation or dictated by tests that prevents iterators from consuming from inner iterators, which will cause unnecessary runtime overhead and possibly surprising users if they re-use the inner iterators later.
Describe the solution you'd like
- Introduce a new nomenclature for discussing iterators in documentation in order to make talking about them easier. a "primary" iterator is an original producer of values, it does not depend on underlying iterators (e.g.
Count). A "second-order" iterator is one which depends on another iterator (e.g.Take). - Documentation should be clear for each iterator whether it is "primary" or "second-order".
- Documentation should be clear that "second-order" iterators that are exhausted should *cease consumption" of their underlying iterators on subsequent calls to
Next. - All existing "second-order" iterators in the
iterpackage should have tests that guarantee this behaviour.
Provide code snippets to show how this new feature might be used.
N/A documentation change.
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
Maybe - I'd prefer to give someone else the opportunity to contribute.
Additional context
PRs that implement part of this are OK, this issue can be closed one all 4 points are addressed.
Hint - I've thought about using counterfeiter to generate a fake iterator in order to make call count testing easier. If you use this, please place a fake iterator inside the internal package of this project.
Alternatively, I'm open to a conversation about the failure of a fake iterator as something iter exposes to make testing easier but that should probably be a separate issue.
Only ZipIter remains, along with documenting which iterators are primary and which are secondary.
Primary iterators: Lift, Repeat, FromChannel, Counter, Exhausted, Lines, LinesString, LiftHashMap, LiftHashMapKeys, LiftHashMapValues.
Second-order iterators: Chain, Drop, Filter, Exclude, Map, FilterMap, Take, Zip.