提交 3a25b65c 编写于 作者: B bors 提交者: GitHub

Auto merge of #37315 - bluss:fold-more, r=alexcrichton

Implement Iterator::fold for .chain(), .cloned(), .map() and the VecDeque iterators.

Chain can do something interesting here where it passes on the fold
into its inner iterators.

The lets the underlying iterator's custom fold() be used, and skips the
regular chain logic in next.

Also implement .fold() specifically for .map() and .cloned() so that any
inner fold improvements are available through map and cloned.

The same way, a VecDeque iterator fold can be turned into two slice folds.

These changes lend the power of the slice iterator's loop codegen to
VecDeque, and to chains of slice iterators, and so on.
It's an improvement for .sum() and .product(), and other uses of fold.
...@@ -743,16 +743,8 @@ pub fn iter_mut(&mut self) -> IterMut<T> { ...@@ -743,16 +743,8 @@ pub fn iter_mut(&mut self) -> IterMut<T> {
#[stable(feature = "deque_extras_15", since = "1.5.0")] #[stable(feature = "deque_extras_15", since = "1.5.0")]
pub fn as_slices(&self) -> (&[T], &[T]) { pub fn as_slices(&self) -> (&[T], &[T]) {
unsafe { unsafe {
let contiguous = self.is_contiguous();
let buf = self.buffer_as_slice(); let buf = self.buffer_as_slice();
if contiguous { RingSlices::ring_slices(buf, self.head, self.tail)
let (empty, buf) = buf.split_at(0);
(&buf[self.tail..self.head], empty)
} else {
let (mid, right) = buf.split_at(self.tail);
let (left, _) = mid.split_at(self.head);
(right, left)
}
} }
} }
...@@ -780,20 +772,10 @@ pub fn as_slices(&self) -> (&[T], &[T]) { ...@@ -780,20 +772,10 @@ pub fn as_slices(&self) -> (&[T], &[T]) {
#[stable(feature = "deque_extras_15", since = "1.5.0")] #[stable(feature = "deque_extras_15", since = "1.5.0")]
pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) { pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
unsafe { unsafe {
let contiguous = self.is_contiguous();
let head = self.head; let head = self.head;
let tail = self.tail; let tail = self.tail;
let buf = self.buffer_as_mut_slice(); let buf = self.buffer_as_mut_slice();
RingSlices::ring_slices(buf, head, tail)
if contiguous {
let (empty, buf) = buf.split_at_mut(0);
(&mut buf[tail..head], empty)
} else {
let (mid, right) = buf.split_at_mut(tail);
let (left, _) = mid.split_at_mut(head);
(right, left)
}
} }
} }
...@@ -1829,6 +1811,42 @@ fn wrap_index(index: usize, size: usize) -> usize { ...@@ -1829,6 +1811,42 @@ fn wrap_index(index: usize, size: usize) -> usize {
index & (size - 1) index & (size - 1)
} }
/// Returns the two slices that cover the VecDeque's valid range
trait RingSlices : Sized {
fn slice(self, from: usize, to: usize) -> Self;
fn split_at(self, i: usize) -> (Self, Self);
fn ring_slices(buf: Self, head: usize, tail: usize) -> (Self, Self) {
let contiguous = tail <= head;
if contiguous {
let (empty, buf) = buf.split_at(0);
(buf.slice(tail, head), empty)
} else {
let (mid, right) = buf.split_at(tail);
let (left, _) = mid.split_at(head);
(right, left)
}
}
}
impl<'a, T> RingSlices for &'a [T] {
fn slice(self, from: usize, to: usize) -> Self {
&self[from..to]
}
fn split_at(self, i: usize) -> (Self, Self) {
(*self).split_at(i)
}
}
impl<'a, T> RingSlices for &'a mut [T] {
fn slice(self, from: usize, to: usize) -> Self {
&mut self[from..to]
}
fn split_at(self, i: usize) -> (Self, Self) {
(*self).split_at_mut(i)
}
}
/// Calculate the number of elements left to be read in the buffer /// Calculate the number of elements left to be read in the buffer
#[inline] #[inline]
fn count(tail: usize, head: usize, size: usize) -> usize { fn count(tail: usize, head: usize, size: usize) -> usize {
...@@ -1875,6 +1893,14 @@ fn size_hint(&self) -> (usize, Option<usize>) { ...@@ -1875,6 +1893,14 @@ fn size_hint(&self) -> (usize, Option<usize>) {
let len = count(self.tail, self.head, self.ring.len()); let len = count(self.tail, self.head, self.ring.len());
(len, Some(len)) (len, Some(len))
} }
fn fold<Acc, F>(self, mut accum: Acc, mut f: F) -> Acc
where F: FnMut(Acc, Self::Item) -> Acc,
{
let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
accum = front.iter().fold(accum, &mut f);
back.iter().fold(accum, &mut f)
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
...@@ -1927,6 +1953,14 @@ fn size_hint(&self) -> (usize, Option<usize>) { ...@@ -1927,6 +1953,14 @@ fn size_hint(&self) -> (usize, Option<usize>) {
let len = count(self.tail, self.head, self.ring.len()); let len = count(self.tail, self.head, self.ring.len());
(len, Some(len)) (len, Some(len))
} }
fn fold<Acc, F>(self, mut accum: Acc, mut f: F) -> Acc
where F: FnMut(Acc, Self::Item) -> Acc,
{
let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
accum = front.iter_mut().fold(accum, &mut f);
back.iter_mut().fold(accum, &mut f)
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
......
...@@ -399,6 +399,12 @@ fn next(&mut self) -> Option<T> { ...@@ -399,6 +399,12 @@ fn next(&mut self) -> Option<T> {
fn size_hint(&self) -> (usize, Option<usize>) { fn size_hint(&self) -> (usize, Option<usize>) {
self.it.size_hint() self.it.size_hint()
} }
fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc
where F: FnMut(Acc, Self::Item) -> Acc,
{
self.it.fold(init, move |acc, elt| f(acc, elt.clone()))
}
} }
#[stable(feature = "iter_cloned", since = "1.1.0")] #[stable(feature = "iter_cloned", since = "1.1.0")]
...@@ -544,6 +550,25 @@ fn count(self) -> usize { ...@@ -544,6 +550,25 @@ fn count(self) -> usize {
} }
} }
fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc
where F: FnMut(Acc, Self::Item) -> Acc,
{
let mut accum = init;
match self.state {
ChainState::Both | ChainState::Front => {
accum = self.a.fold(accum, &mut f);
}
_ => { }
}
match self.state {
ChainState::Both | ChainState::Back => {
accum = self.b.fold(accum, &mut f);
}
_ => { }
}
accum
}
#[inline] #[inline]
fn nth(&mut self, mut n: usize) -> Option<A::Item> { fn nth(&mut self, mut n: usize) -> Option<A::Item> {
match self.state { match self.state {
...@@ -939,6 +964,13 @@ fn next(&mut self) -> Option<B> { ...@@ -939,6 +964,13 @@ fn next(&mut self) -> Option<B> {
fn size_hint(&self) -> (usize, Option<usize>) { fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint() self.iter.size_hint()
} }
fn fold<Acc, G>(self, init: Acc, mut g: G) -> Acc
where G: FnMut(Acc, Self::Item) -> Acc,
{
let mut f = self.f;
self.iter.fold(init, move |acc, elt| g(acc, f(elt)))
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
......
...@@ -985,6 +985,18 @@ fn test_empty() { ...@@ -985,6 +985,18 @@ fn test_empty() {
assert_eq!(it.next(), None); assert_eq!(it.next(), None);
} }
#[test]
fn test_chain_fold() {
let xs = [1, 2, 3];
let ys = [1, 2, 0];
let mut iter = xs.iter().chain(&ys);
iter.next();
let mut result = Vec::new();
iter.fold((), |(), &elt| result.push(elt));
assert_eq!(&[2, 3, 1, 2, 0], &result[..]);
}
#[bench] #[bench]
fn bench_rposition(b: &mut Bencher) { fn bench_rposition(b: &mut Bencher) {
let it: Vec<usize> = (0..300).collect(); let it: Vec<usize> = (0..300).collect();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册