Skip to content

Commit

Permalink
Merge #699
Browse files Browse the repository at this point in the history
699: Position<Item> -> (Position, Item) r=jswrenn a=phimuemue

As suggested in #651, we could simplify `with_position`'s API by yielding `(Position, Item)` instead of `Position<Item>`.

Note: This is a breaking change.

Co-authored-by: philipp <descpl@yahoo.de>
  • Loading branch information
bors[bot] and phimuemue committed Jun 14, 2023
2 parents ad2e401 + 2b04a4f commit 878e662
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 31 deletions.
14 changes: 7 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1657,24 +1657,24 @@ pub trait Itertools : Iterator {
pad_tail::pad_using(self, min, f)
}

/// Return an iterator adaptor that wraps each element in a `Position` to
/// Return an iterator adaptor that combines each element with a `Position` to
/// ease special-case handling of the first or last elements.
///
/// Iterator element type is
/// [`Position<Self::Item>`](Position)
/// [`(Position, Self::Item)`](Position)
///
/// ```
/// use itertools::{Itertools, Position};
///
/// let it = (0..4).with_position();
/// itertools::assert_equal(it,
/// vec![Position::First(0),
/// Position::Middle(1),
/// Position::Middle(2),
/// Position::Last(3)]);
/// vec![(Position::First, 0),
/// (Position::Middle, 1),
/// (Position::Middle, 2),
/// (Position::Last, 3)]);
///
/// let it = (0..1).with_position();
/// itertools::assert_equal(it, vec![Position::Only(0)]);
/// itertools::assert_equal(it, vec![(Position::Only, 0)]);
/// ```
fn with_position(self) -> WithPosition<Self>
where Self: Sized,
Expand Down
36 changes: 12 additions & 24 deletions src/with_position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::iter::{Fuse,Peekable, FusedIterator};

/// An iterator adaptor that wraps each element in an [`Position`].
///
/// Iterator element type is `Position<I::Item>`.
/// Iterator element type is `(Position, I::Item)`.
///
/// See [`.with_position()`](crate::Itertools::with_position) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
Expand Down Expand Up @@ -30,36 +30,24 @@ pub fn with_position<I>(iter: I) -> WithPosition<I>
}
}

/// A value yielded by `WithPosition`.
/// The first component of the value yielded by `WithPosition`.
/// Indicates the position of this element in the iterator results.
///
/// See [`.with_position()`](crate::Itertools::with_position) for more information.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Position<T> {
pub enum Position {
/// This is the first element.
First(T),
First,
/// This is neither the first nor the last element.
Middle(T),
Middle,
/// This is the last element.
Last(T),
Last,
/// This is the only element.
Only(T),
}

impl<T> Position<T> {
/// Return the inner value.
pub fn into_inner(self) -> T {
match self {
Position::First(x) |
Position::Middle(x) |
Position::Last(x) |
Position::Only(x) => x,
}
}
Only,
}

impl<I: Iterator> Iterator for WithPosition<I> {
type Item = Position<I::Item>;
type Item = (Position, I::Item);

fn next(&mut self) -> Option<Self::Item> {
match self.peekable.next() {
Expand All @@ -70,15 +58,15 @@ impl<I: Iterator> Iterator for WithPosition<I> {
// Peek to see if this is also the last item,
// in which case tag it as `Only`.
match self.peekable.peek() {
Some(_) => Some(Position::First(item)),
None => Some(Position::Only(item)),
Some(_) => Some((Position::First, item)),
None => Some((Position::Only, item)),
}
} else {
// Have seen the first item, and there's something left.
// Peek to see if this is the last item.
match self.peekable.peek() {
Some(_) => Some(Position::Middle(item)),
None => Some(Position::Last(item)),
Some(_) => Some((Position::Middle, item)),
None => Some((Position::Last, item)),
}
}
}
Expand Down

0 comments on commit 878e662

Please sign in to comment.