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

Add .get(range) #891

Merged
merged 10 commits into from
May 14, 2024
Merged

Conversation

Philippe-Cholet
Copy link
Member

@Philippe-Cholet Philippe-Cholet commented Mar 1, 2024

Closes #447.

So much changes happened since this work was initiated that rebase on top of master seems nothing less than a nightmare to me (I know, I tried). I therefore looked at the git differences, committed those (after formatting) and credited @wod3 and @TrolledWoods for their respective commits. Then I fixed my own review and a bit more.


I thought I would additionally implement IteratorIndex for Either<range, range> (and Box<dyn range> but I could not) but doing so would later result in a nasty breaking change if this was removed after an eventual inclusion to Iterator.

Details about either
    impl<L: Sealed, R: Sealed> Sealed for either::Either<L, R> {}


impl<I, L, R> IteratorIndex<I> for Either<L, R>
where
    I: Iterator,
    L: IteratorIndex<I>,
    R: IteratorIndex<I>,
{
    type Output = Either<<L as IteratorIndex<I>>::Output, <R as IteratorIndex<I>>::Output>;

    fn index(self, iter: I) -> Self::Output {
        // Could be more succinct with `map_either_with` but it would require to bump `either` version.
        match self {
            Either::Left(left) => Either::Left(left.index(iter)),
            Either::Right(right) => Either::Right(right.index(iter)),
        }
    }
}


    /// // It works nicely with either.
    /// use itertools::Either;
    ///
    /// let mut either_range = Either::Left(0..1);
    /// range = vec.iter().get(either_range).copied().collect();
    /// assert_eq!(&range, &[3]);
    ///
    /// either_range = Either::Right(2..);
    /// range = vec.iter().get(either_range).copied().collect();
    /// assert_eq!(&range, &[4, 1, 5]);

Copy link

codecov bot commented Mar 1, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 94.57%. Comparing base (6814180) to head (3f49188).
Report is 79 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #891      +/-   ##
==========================================
+ Coverage   94.38%   94.57%   +0.18%     
==========================================
  Files          48       49       +1     
  Lines        6665     7002     +337     
==========================================
+ Hits         6291     6622     +331     
- Misses        374      380       +6     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

src/iter_index.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@scottmcm scottmcm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of these are just things to ponder that might not need changing, but I think at least the overflow thing should be tweaked.

src/iter_index.rs Show resolved Hide resolved
src/iter_index.rs Outdated Show resolved Hide resolved
src/lib.rs Outdated Show resolved Hide resolved
src/iter_index.rs Outdated Show resolved Hide resolved
@Philippe-Cholet
Copy link
Member Author

Philippe-Cholet commented May 2, 2024

I rebased on master and added 4 commits:

  1. Is there a reason to prefer Take<Skip> over Skip<Take>? As Skip<Take> is simpler defined!
  2. I don't see how we should really handle a range that includes usize::MAX other than with panic.
  3. Clarified when the resulting iterator is ExactSizeIterator and/or DoubleEndedIterator.
  4. fix 2nd commit: .get(1..=usize::MAX) should be fine (EDIT: tested).

And removed get as a free function.

@Philippe-Cholet Philippe-Cholet force-pushed the 447-get-range branch 3 times, most recently from 6477ac0 to de08253 Compare May 3, 2024 06:38
@Philippe-Cholet Philippe-Cholet added this to the next milestone May 4, 2024
Philippe-Cholet and others added 8 commits May 14, 2024 10:11
Co-Authored-By: wod3 <17980899+wod3@users.noreply.github.com>
Co-Authored-By: TrolledWoods <26680270+trolledwoods@users.noreply.github.com>
Fix my own review.
Update docs.
Fix a warning with `#[cfg(doc)]`.
Use public path `traits::IteratorIndex` instead of private path `iter_index::IteratorIndex`.
As we should, I checked it can't pass without `let _ =`.
`RangeInclusive::is_empty` (rust 1.47+) is in conflict with our MSRV (1.43.1) so we can't use it yet.
The unspecified behavior is documented in `Itertools::get` so we simply remove this.
Unless there is a reason to prefer `Take<Skip>` over `Skip<Take>`?!
A `use itertools::*;` might conflict with such a general function name.
Copy link
Member

@jswrenn jswrenn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tremendous thanks for getting this over the finish line! This looks fantastic.

@jswrenn jswrenn added this pull request to the merge queue May 14, 2024
Merged via the queue into rust-itertools:master with commit 0d4efc8 May 14, 2024
13 checks passed
@Philippe-Cholet Philippe-Cholet deleted the 447-get-range branch May 14, 2024 14:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants