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

Merge multipeek peeknth #940

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

Owen-CH-Leung
Copy link
Contributor

As per #933 , this PR merges MultiPeek and PeekNth into a general private interface MultiPeekGeneral, with public type alias to define the compatible MultiPeek and PeekNth struct.

Copy link

codecov bot commented May 17, 2024

Codecov Report

Attention: Patch coverage is 78.26087% with 15 lines in your changes are missing coverage. Please review.

Project coverage is 94.32%. Comparing base (6814180) to head (4fc8456).
Report is 94 commits behind head on master.

Files Patch % Lines
src/multipeek_general.rs 77.94% 15 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #940      +/-   ##
==========================================
- Coverage   94.38%   94.32%   -0.07%     
==========================================
  Files          48       48              
  Lines        6665     7013     +348     
==========================================
+ Hits         6291     6615     +324     
- Misses        374      398      +24     

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

Copy link
Member

@Philippe-Cholet Philippe-Cholet left a comment

Choose a reason for hiding this comment

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

I reviewed but I'm not sure we should continue this, as merge implementations imply to merge method documentations, while the index behavior is different.
@phimuemue What do you think? Was I overzealous here?

src/lib.rs Outdated
Comment on lines 117 to 120
#[cfg(feature = "use_alloc")]
pub use crate::multipeek_impl::MultiPeek;
pub use crate::pad_tail::PadUsing;
pub use crate::multipeek_general::MultiPeek;
#[cfg(feature = "use_alloc")]
pub use crate::peek_nth::PeekNth;
pub use crate::multipeek_general::PeekNth;
Copy link
Member

Choose a reason for hiding this comment

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

You can merge those imports.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup - merged.

Comment on lines 244 to 246
impl<I: Iterator, Idx: PeekIndex> PeekingNext for MultiPeekGeneral<I, Idx>
where
I: Iterator,
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Iterator bound twice, move Idx bound below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks. Moved Idx bound below

where
I: Iterator,
{
fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
where
F: FnOnce(&Self::Item) -> bool,
{
self.peek().filter(|item| accept(item))?;
self.peek_mut().filter(|item| accept(item))?;
Copy link
Member

Choose a reason for hiding this comment

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

I don't see why it would now need peek_mut.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks. Reverted to peek

Comment on lines 196 to 218
pub fn peek(&mut self) -> Option<&I::Item> {
let ret = if self.index < self.buf.len() {
Some(&self.buf[self.index])
} else {
match self.iter.next() {
Some(x) => {
self.buf.push_back(x);
Some(&self.buf[self.index])
}
None => return None,
}
};

self.index += 1;
ret
}
}

impl<I: Iterator> PeekNth<I> {
/// Works exactly like the `peek` method in [`std::iter::Peekable`].
pub fn peek(&mut self) -> Option<&I::Item> {
self.peek_nth(0)
}
Copy link
Member

Choose a reason for hiding this comment

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

I think it could be merged into MultiPeekGeneral::peek? With a PeekIndex::increment_index.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes - I've merged peek into MultiPeekGeneral and removed the impl block

Comment on lines 26 to 27
/// [`IntoIterator`] enabled version of [`crate::Itertools::multipeek`].
pub fn multipeek<I>(iterable: I) -> MultiPeek<I::IntoIter>
Copy link
Member

Choose a reason for hiding this comment

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

To avoid crate:: to be user-visible in doc, we usually do:

  • [`Itertools::multipeek`](crate::Itertools::multipeek) which I usually prefer
  • (OR #[cfg(doc)] use crate::Itertools; at the top of the file to be able to only write [`Itertools::multipeek`] in the doc).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks. I've revised to use

[`Itertools::multipeek`](crate::Itertools::multipeek) 

Comment on lines 1 to 2
#![allow(private_interfaces)]
#![allow(private_bounds)]
Copy link
Member

Choose a reason for hiding this comment

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

I discover those lints, or rather I probably usually fix what those lints tell me rather than allow them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are right. Turns out it passes the clippy even the lints are removed. I've removed them

src/free.rs Outdated
Comment on lines 22 to 25
#[cfg(feature = "use_alloc")]
pub use crate::multipeek_impl::multipeek;
pub use crate::multipeek_general::multipeek;
#[cfg(feature = "use_alloc")]
pub use crate::peek_nth::peek_nth;
pub use crate::multipeek_general::peek_nth;
Copy link
Member

Choose a reason for hiding this comment

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

You can merge those lines.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Merged

Comment on lines 12 to 14
pub iter: Fuse<I>,
pub buf: VecDeque<I::Item>,
pub index: Idx,
Copy link
Member

Choose a reason for hiding this comment

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

Almost missed this. The fields should remain private! If there is a need to access them from another module, you can pub(crate) the fields.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks - I've changed them to private fields

Comment on lines 60 to 62
impl PeekIndex for () {
fn reset_index(&mut self) {}
}
Copy link
Member

Choose a reason for hiding this comment

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

I mention elsewhere the need to add a fn increment_index(&mut self); but we probably need a more general fn add(&mut self, n: usize) { *self += n; } instead to update the index with the nth methods (and create tests about it).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure. I've revised increment_index to a generic add instead.

@@ -137,15 +165,64 @@ where
{
self.next_if(|next| next == expected)
}

/// Works exactly like `next_if`, but for the `nth` value without advancing the iterator.
pub fn nth_if(&mut self, n: usize, func: impl FnOnce(&I::Item) -> bool) -> Option<&I::Item> {
Copy link
Member

Choose a reason for hiding this comment

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

What should we expect from MultiPeek::nth_if concerning the index? To advance only if func returned true I guess. But I would expect the doc of the method to decribe this but we can't make different docs for MultiPeek/PeekNth without making different methods.
⚠ Maybe I was too optimistic about this merge. ⚠

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe with the merge we'd need to completely revise the doc to describe the API behaviour under MultiPeek and PeekNth. I can help to re-write them if we decide to go for the direction to merge both.

@phimuemue
Copy link
Member

My suggestion: Deprecate multipeek and unify all the functionality into peek_nth.

Rationale: peek_nth is (advertised as) a drop-in replacement for std::iter::Peekable (nice for users), whereas multipeek offers exactly the same interface, but has subtle semantic differences (not nice for users if they are bitten by this).

And imho we should even un-fuse it to really be in line with std::iter::Peekable.

@Philippe-Cholet
Copy link
Member

According to https://github.com/search?q=itertools+multipeek+reset_peek+lang%3ARust&type=code there is some real use of MultiPeek. Deprecate it seems excessive to me.

Maybe the status quo is not so bad.

I'm not opposed to unfuse it but it's a breaking change, I'd prefer to not break things for a while.

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.

None yet

3 participants