BooleanCat / go-functional

go-functional is a library of iterators to augment the standard library
MIT License
405 stars 23 forks source link

Implement tee for iterators #93

Closed BooleanCat closed 3 months ago

BooleanCat commented 7 months ago

Please provide a brief description of the change.

Support tee behaviour for iterators.

Which issue does this change relate to?

88

Contribution checklist.

Replace the space in each box with "X" to check it off.

codecov[bot] commented 7 months ago

Codecov Report

All modified and coverable lines are covered by tests :white_check_mark:

Comparison is base (b3ea617) 100.00% compared to head (eb938d2) 100.00%.

Additional details and impacted files ```diff @@ Coverage Diff @@ ## main #93 +/- ## ========================================= Coverage 100.00% 100.00% ========================================= Files 24 26 +2 Lines 572 637 +65 ========================================= + Hits 572 637 +65 ```

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

BooleanCat commented 7 months ago

@myusko This is a fairly naive implementation of tee. The buffer resizes make it fairly ineffeicient. I'd considered using a linked list instead but it's conceptually more difficult and will take more time for me to figure out.

What do you think about the API for this? I can change how it works under the hood to make it more efficient later but I'd curious about how easy it is to use.

BooleanCat commented 7 months ago

@williammartin I'd be curious too if you have any thoughts on how Tee is used here or better suggestions on making it more efficient than using a linked list or ring instead of a slice.

BooleanCat commented 7 months ago

I'd considered also using two buffered channels but I'd need the channels to be unbounded in size in order to not lock Next from iterators where one is far ahead of the other.

BooleanCat commented 7 months ago

On the usage suggestion - an alternative would be to have Tee directly return the two iterators:

one, two := iter.Count().Take(3).Tee()

I could then make TeeIters private - it's never intended for direct use anyway.

e.g. https://github.com/BooleanCat/go-functional/commit/b8fad8b44a4acaaa4dba52f478f50311a35821c5