Auto merge of #77491 - lukaslueg:peek_mut, r=m-ou-se
Proposal to add Peekable::peek_mut A "peekable" iterator has a `peek()`-method which provides an immutable reference to the next item. We currently do not have a method to modify that item, which we could easily add via a `peek_mut()`. See the test for a use-case (alike to my original use case), where a "pristine" iterator is passed on after modifying its state via `peek_mut()`. If there is interest in this, I can expand on the tests and docs.
This commit is contained in:
commit
b387f62d4d
@ -216,6 +216,43 @@ impl<I: Iterator> Peekable<I> {
|
||||
self.peeked.get_or_insert_with(|| iter.next()).as_ref()
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the next() value without advancing the iterator.
|
||||
///
|
||||
/// Like [`next`], if there is a value, it is wrapped in a `Some(T)`.
|
||||
/// But if the iteration is over, `None` is returned.
|
||||
///
|
||||
/// Because `peek_mut()` returns a reference, and many iterators iterate over
|
||||
/// references, there can be a possibly confusing situation where the
|
||||
/// return value is a double reference. You can see this effect in the examples
|
||||
/// below.
|
||||
///
|
||||
/// [`next`]: Iterator::next
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(peekable_peek_mut)]
|
||||
/// let mut iter = [1, 2, 3].iter().peekable();
|
||||
///
|
||||
/// assert_eq!(iter.peek_mut(), Some(&mut &1));
|
||||
/// assert_eq!(iter.next(), Some(&1));
|
||||
///
|
||||
/// // Peek into the iterator and modify the value which will be returned next
|
||||
/// if let Some(mut p) = iter.peek_mut() {
|
||||
/// if *p == &2 {
|
||||
/// *p = &5;
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(iter.collect::<Vec<_>>(), vec![&5, &3]);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "peekable_peek_mut", issue = "78302")]
|
||||
pub fn peek_mut(&mut self) -> Option<&mut I::Item> {
|
||||
let iter = &mut self.iter;
|
||||
self.peeked.get_or_insert_with(|| iter.next()).as_mut()
|
||||
}
|
||||
|
||||
/// Consume and return the next value of this iterator if a condition is true.
|
||||
///
|
||||
/// If `func` returns `true` for the next value of this iterator, consume and return it.
|
||||
|
@ -1134,6 +1134,17 @@ fn test_iterator_peekable_next_if_eq() {
|
||||
assert_eq!(it.next_if_eq(""), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iterator_peekable_mut() {
|
||||
let mut it = vec![1, 2, 3].into_iter().peekable();
|
||||
if let Some(p) = it.peek_mut() {
|
||||
if *p == 1 {
|
||||
*p = 5;
|
||||
}
|
||||
}
|
||||
assert_eq!(it.collect::<Vec<_>>(), vec![5, 2, 3]);
|
||||
}
|
||||
|
||||
/// This is an iterator that follows the Iterator contract,
|
||||
/// but it is not fused. After having returned None once, it will start
|
||||
/// producing elements if .next() is called again.
|
||||
|
@ -56,6 +56,7 @@
|
||||
#![feature(unwrap_infallible)]
|
||||
#![feature(option_unwrap_none)]
|
||||
#![feature(peekable_next_if)]
|
||||
#![feature(peekable_peek_mut)]
|
||||
#![feature(partition_point)]
|
||||
#![feature(once_cell)]
|
||||
#![feature(unsafe_block_in_unsafe_fn)]
|
||||
|
Loading…
Reference in New Issue
Block a user