Skip to content

Tracking Issue for PeekableIterator #132973

Open

Description

@bluebear94

Feature gate: #![feature(peekable_iterator)]

This is a tracking issue for the PeekableIterator trait, which extends Iterator with peek_with and related methods that inspect the next element without consuming it.

Public API

// core::iter

pub trait PeekableIterator: Iterator {
  // required method
  fn peek_with<T>(&mut self, func: impl for<'a> FnOnce(Option<&'a Self::Item>) -> T) -> T;

  // provided methods
  fn peek_map<T>(&mut self, func: impl for<'a> FnOnce(&'a Self::Item) -> T) -> Option<T>;
  fn next_if(&mut self, func: impl FnOnce(&Self::Item) -> bool) -> Option<Self::Item>;
  fn next_if_eq<T>(&mut self, expected: &T) -> Option<Self::Item>
  where
    Self::Item: PartialEq<T>,
    T: ?Sized;
}

Steps / History

Unresolved Questions

  • Should peek take &mut self or &self? &self makes sense for iterators such as core::slice::iter but precludes implementing the trait on Peekable.
  • What about the return type of peek? We could always make it return Self::Item like itertools’s PeekingNext, but that would prevent this trait from being implemented for consuming iterators such as vec::IntoIter, as well as Peekable itself. Resolved by having the method take a callback.
    • If we use an associated type, then what should be the bound for it: Borrow, AsRef, or something else?

Footnotes

  1. https://std-dev-guide.rust-lang.org/feature-lifecycle/stabilization.html ↩

Activity

  1. added
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    T-libs-api[DEPRECATED; DO NOT USE]
    on Nov 12, 2024
  2. YkdWaWEzVmphR1Z1 commented on Jan 3, 2025

    @YkdWaWEzVmphR1Z1

    Wouldn't it be a lot more general for the item to be an iterator. Peek could be implemented in terms of <Self::PeekedItem as PeekedIterator>::peek_iter.next(). Peekable stores an Option, so it would just return an Option Iterator. But a slice for example could return slice::Iter. I also wonder what benefit this brings over methods on the iterator types. The example uses the Chars iterator, but it also as an as_str() method. The same applies for slice and the range types. So the trait would only be useful in generic code and for that it had to be a lot more general than it currently is.

    This design is the Peekable struct as trait. The Peekable struct has been designed this way, because it has to work with any iterator. But many iterators can just return cheaply a new iterator without changing the old iterator. This applies probably to any iterator which does not store a closure and whose internal iterator does not have side effects.

  3. bluebear94 commented on Apr 16, 2025

    @bluebear94
    ContributorAuthor

    This still leaves the problem of what type of element the returned iterator yields. For Peekable<impl Iterator<Item=T>> and slice::Iter<T>, this should be &T, but for Range<T>, the iterator would have to be over T.

  4. theemathas commented on Aug 5, 2025

    @theemathas
    Contributor

    Maybe the correct function signature is this?

    fn peek<T>(&mut self, callback: impl for<'a> FnOnce(Option<&'a Self::Item>) -> T) -> T

    This would mean, for example, that str::Chars would be able to implement this without having a field inside the iterator that contains a char. Instead, it would be able to create a local variable in the peek method that stores the char.

  5. wmstack commented on Aug 5, 2025

    @wmstack
    Contributor

    I like this method signature, although I think the parameter with an Option is a little difficult to work with inside a closure. next_if signature callback takes func: impl FnOnce(&Self::Item) -> bool), so it might be more convenient to move the Option outside. Alternatively, a little helper peek_map can be added that does that.

    fn peek<T>(&mut self, callback: impl for<'a> FnOnce(Option<&'a Self::Item>) -> T) -> T
    
    // run a closure on the peeked value returning the output
    fn peek_map<T>(&mut self, func: impl for<'a> FnOnce(&'a Self::Item) -> T) -> Option<T> {
       self.peek(|x| x.map(|y| func(y)))
    }
  6. added
    T-libsRelevant to the library team, which will review and decide on the PR/issue.
    and removed
    T-libs-api[DEPRECATED; DO NOT USE]
    on Aug 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCT-libsRelevant to the library team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions