auto merge of #9634 : blake2-ppc/rust/by-ref-iter, r=thestinger
std::iter: Introduce .by_ref() adaptor Creates a wrapper around a mutable reference to the iterator. This is useful to allow applying iterator adaptors while still retaining ownership of the original iterator value. Example:: let mut xs = range(0, 10); // sum the first five values let partial_sum = xs.by_ref().take(5).fold(0, |a, b| a + b); assert!(partial_sum == 10); // xs.next() is now `5` assert!(xs.next() == Some(5)); --- This adaptor requires the user to have good understanding of iterators or what a particular adaptor does. There could be some pitfalls here with the iterator protocol, it's mostly the same issues as other places regarding what happens after the iterator returns None for the first time. There could also be other ways to achieve the same thing, for example Implementing iterator on `&mut T` itself: `impl <T: Iterator<..>> Iterator for &mut T` but that would only lead to confusion I think.
This commit is contained in:
commit
63e097d8c3
@ -405,6 +405,25 @@ pub trait Iterator<A> {
|
||||
Inspect{iter: self, f: f}
|
||||
}
|
||||
|
||||
/// Creates a wrapper around a mutable reference to the iterator.
|
||||
///
|
||||
/// This is useful to allow applying iterator adaptors while still
|
||||
/// retaining ownership of the original iterator value.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// let mut xs = range(0, 10);
|
||||
/// // sum the first five values
|
||||
/// let partial_sum = xs.by_ref().take(5).fold(0, |a, b| a + b);
|
||||
/// assert!(partial_sum == 10);
|
||||
/// // xs.next() is now `5`
|
||||
/// assert!(xs.next() == Some(5));
|
||||
/// ```
|
||||
fn by_ref<'r>(&'r mut self) -> ByRef<'r, Self> {
|
||||
ByRef{iter: self}
|
||||
}
|
||||
|
||||
/// An adaptation of an external iterator to the for-loop protocol of rust.
|
||||
///
|
||||
/// # Example
|
||||
@ -771,6 +790,22 @@ impl<A, T: DoubleEndedIterator<A> + RandomAccessIterator<A>> RandomAccessIterato
|
||||
}
|
||||
}
|
||||
|
||||
/// A mutable reference to an iterator
|
||||
pub struct ByRef<'self, T> {
|
||||
priv iter: &'self mut T
|
||||
}
|
||||
|
||||
impl<'self, A, T: Iterator<A>> Iterator<A> for ByRef<'self, T> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> { self.iter.next() }
|
||||
// FIXME: #9629 we cannot implement &self methods like size_hint on ByRef
|
||||
}
|
||||
|
||||
impl<'self, A, T: DoubleEndedIterator<A>> DoubleEndedIterator<A> for ByRef<'self, T> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<A> { self.iter.next_back() }
|
||||
}
|
||||
|
||||
/// A trait for iterators over elements which can be added together
|
||||
pub trait AdditiveIterator<A> {
|
||||
/// Iterates over the entire iterator, summing up all the elements
|
||||
@ -2500,6 +2535,15 @@ mod tests {
|
||||
assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_by_ref() {
|
||||
let mut xs = range(0, 10);
|
||||
// sum the first five values
|
||||
let partial_sum = xs.by_ref().take(5).fold(0, |a, b| a + b);
|
||||
assert_eq!(partial_sum, 10);
|
||||
assert_eq!(xs.next(), Some(5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invert() {
|
||||
let xs = [2, 4, 6, 8, 10, 12, 14, 16];
|
||||
|
Loading…
x
Reference in New Issue
Block a user