From 4a036142a0da3cbae374f824a332bc43d4cecd09 Mon Sep 17 00:00:00 2001 From: Clar Fon Date: Mon, 17 Dec 2018 17:33:12 -0500 Subject: [PATCH] Move Sum, Product to own module --- src/libcore/iter/traits/accum.rs | 225 ++++++++++++++++++++++++++++++ src/libcore/iter/traits/mod.rs | 228 +------------------------------ 2 files changed, 227 insertions(+), 226 deletions(-) create mode 100644 src/libcore/iter/traits/accum.rs diff --git a/src/libcore/iter/traits/accum.rs b/src/libcore/iter/traits/accum.rs new file mode 100644 index 000000000000..dfe1d2a1006d --- /dev/null +++ b/src/libcore/iter/traits/accum.rs @@ -0,0 +1,225 @@ +use ops::{Mul, Add}; +use num::Wrapping; + +/// Trait to represent types that can be created by summing up an iterator. +/// +/// This trait is used to implement the [`sum`] method on iterators. Types which +/// implement the trait can be generated by the [`sum`] method. Like +/// [`FromIterator`] this trait should rarely be called directly and instead +/// interacted with through [`Iterator::sum`]. +/// +/// [`sum`]: ../../std/iter/trait.Sum.html#tymethod.sum +/// [`FromIterator`]: ../../std/iter/trait.FromIterator.html +/// [`Iterator::sum`]: ../../std/iter/trait.Iterator.html#method.sum +#[stable(feature = "iter_arith_traits", since = "1.12.0")] +pub trait Sum: Sized { + /// Method which takes an iterator and generates `Self` from the elements by + /// "summing up" the items. + #[stable(feature = "iter_arith_traits", since = "1.12.0")] + fn sum>(iter: I) -> Self; +} + +/// Trait to represent types that can be created by multiplying elements of an +/// iterator. +/// +/// This trait is used to implement the [`product`] method on iterators. Types +/// which implement the trait can be generated by the [`product`] method. Like +/// [`FromIterator`] this trait should rarely be called directly and instead +/// interacted with through [`Iterator::product`]. +/// +/// [`product`]: ../../std/iter/trait.Product.html#tymethod.product +/// [`FromIterator`]: ../../std/iter/trait.FromIterator.html +/// [`Iterator::product`]: ../../std/iter/trait.Iterator.html#method.product +#[stable(feature = "iter_arith_traits", since = "1.12.0")] +pub trait Product: Sized { + /// Method which takes an iterator and generates `Self` from the elements by + /// multiplying the items. + #[stable(feature = "iter_arith_traits", since = "1.12.0")] + fn product>(iter: I) -> Self; +} + +// N.B., explicitly use Add and Mul here to inherit overflow checks +macro_rules! integer_sum_product { + (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($( + #[$attr] + impl Sum for $a { + fn sum>(iter: I) -> $a { + iter.fold($zero, Add::add) + } + } + + #[$attr] + impl Product for $a { + fn product>(iter: I) -> $a { + iter.fold($one, Mul::mul) + } + } + + #[$attr] + impl<'a> Sum<&'a $a> for $a { + fn sum>(iter: I) -> $a { + iter.fold($zero, Add::add) + } + } + + #[$attr] + impl<'a> Product<&'a $a> for $a { + fn product>(iter: I) -> $a { + iter.fold($one, Mul::mul) + } + } + )*); + ($($a:ty)*) => ( + integer_sum_product!(@impls 0, 1, + #[stable(feature = "iter_arith_traits", since = "1.12.0")], + $($a)+); + integer_sum_product!(@impls Wrapping(0), Wrapping(1), + #[stable(feature = "wrapping_iter_arith", since = "1.14.0")], + $(Wrapping<$a>)+); + ); +} + +macro_rules! float_sum_product { + ($($a:ident)*) => ($( + #[stable(feature = "iter_arith_traits", since = "1.12.0")] + impl Sum for $a { + fn sum>(iter: I) -> $a { + iter.fold(0.0, |a, b| a + b) + } + } + + #[stable(feature = "iter_arith_traits", since = "1.12.0")] + impl Product for $a { + fn product>(iter: I) -> $a { + iter.fold(1.0, |a, b| a * b) + } + } + + #[stable(feature = "iter_arith_traits", since = "1.12.0")] + impl<'a> Sum<&'a $a> for $a { + fn sum>(iter: I) -> $a { + iter.fold(0.0, |a, b| a + *b) + } + } + + #[stable(feature = "iter_arith_traits", since = "1.12.0")] + impl<'a> Product<&'a $a> for $a { + fn product>(iter: I) -> $a { + iter.fold(1.0, |a, b| a * *b) + } + } + )*) +} + +integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } +float_sum_product! { f32 f64 } + +/// An iterator adapter that produces output as long as the underlying +/// iterator produces `Result::Ok` values. +/// +/// If an error is encountered, the iterator stops and the error is +/// stored. The error may be recovered later via `reconstruct`. +struct ResultShunt { + iter: I, + error: Option, +} + +impl ResultShunt + where I: Iterator> +{ + /// Process the given iterator as if it yielded a `T` instead of a + /// `Result`. Any errors will stop the inner iterator and + /// the overall result will be an error. + pub fn process(iter: I, mut f: F) -> Result + where F: FnMut(&mut Self) -> U + { + let mut shunt = ResultShunt::new(iter); + let value = f(shunt.by_ref()); + shunt.reconstruct(value) + } + + fn new(iter: I) -> Self { + ResultShunt { + iter, + error: None, + } + } + + /// Consume the adapter and rebuild a `Result` value. This should + /// *always* be called, otherwise any potential error would be + /// lost. + fn reconstruct(self, val: U) -> Result { + match self.error { + None => Ok(val), + Some(e) => Err(e), + } + } +} + +impl Iterator for ResultShunt + where I: Iterator> +{ + type Item = T; + + fn next(&mut self) -> Option { + match self.iter.next() { + Some(Ok(v)) => Some(v), + Some(Err(e)) => { + self.error = Some(e); + None + } + None => None, + } + } + + fn size_hint(&self) -> (usize, Option) { + if self.error.is_some() { + (0, Some(0)) + } else { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } + } +} + +#[stable(feature = "iter_arith_traits_result", since="1.16.0")] +impl Sum> for Result + where T: Sum, +{ + /// Takes each element in the `Iterator`: if it is an `Err`, no further + /// elements are taken, and the `Err` is returned. Should no `Err` occur, + /// the sum of all elements is returned. + /// + /// # Examples + /// + /// This sums up every integer in a vector, rejecting the sum if a negative + /// element is encountered: + /// + /// ``` + /// let v = vec![1, 2]; + /// let res: Result = v.iter().map(|&x: &i32| + /// if x < 0 { Err("Negative element found") } + /// else { Ok(x) } + /// ).sum(); + /// assert_eq!(res, Ok(3)); + /// ``` + fn sum(iter: I) -> Result + where I: Iterator>, + { + ResultShunt::process(iter, |i| i.sum()) + } +} + +#[stable(feature = "iter_arith_traits_result", since="1.16.0")] +impl Product> for Result + where T: Product, +{ + /// Takes each element in the `Iterator`: if it is an `Err`, no further + /// elements are taken, and the `Err` is returned. Should no `Err` occur, + /// the product of all elements is returned. + fn product(iter: I) -> Result + where I: Iterator>, + { + ResultShunt::process(iter, |i| i.product()) + } +} diff --git a/src/libcore/iter/traits/mod.rs b/src/libcore/iter/traits/mod.rs index 093799d7bce2..25637ef9f4ed 100644 --- a/src/libcore/iter/traits/mod.rs +++ b/src/libcore/iter/traits/mod.rs @@ -1,238 +1,14 @@ -use ops::{Mul, Add}; -use num::Wrapping; - mod iterator; mod double_ended; mod exact_size; mod collect; +mod accum; pub use self::iterator::Iterator; pub use self::double_ended::DoubleEndedIterator; pub use self::exact_size::ExactSizeIterator; pub use self::collect::{FromIterator, IntoIterator, Extend}; - -/// Trait to represent types that can be created by summing up an iterator. -/// -/// This trait is used to implement the [`sum`] method on iterators. Types which -/// implement the trait can be generated by the [`sum`] method. Like -/// [`FromIterator`] this trait should rarely be called directly and instead -/// interacted with through [`Iterator::sum`]. -/// -/// [`sum`]: ../../std/iter/trait.Sum.html#tymethod.sum -/// [`FromIterator`]: ../../std/iter/trait.FromIterator.html -/// [`Iterator::sum`]: ../../std/iter/trait.Iterator.html#method.sum -#[stable(feature = "iter_arith_traits", since = "1.12.0")] -pub trait Sum: Sized { - /// Method which takes an iterator and generates `Self` from the elements by - /// "summing up" the items. - #[stable(feature = "iter_arith_traits", since = "1.12.0")] - fn sum>(iter: I) -> Self; -} - -/// Trait to represent types that can be created by multiplying elements of an -/// iterator. -/// -/// This trait is used to implement the [`product`] method on iterators. Types -/// which implement the trait can be generated by the [`product`] method. Like -/// [`FromIterator`] this trait should rarely be called directly and instead -/// interacted with through [`Iterator::product`]. -/// -/// [`product`]: ../../std/iter/trait.Product.html#tymethod.product -/// [`FromIterator`]: ../../std/iter/trait.FromIterator.html -/// [`Iterator::product`]: ../../std/iter/trait.Iterator.html#method.product -#[stable(feature = "iter_arith_traits", since = "1.12.0")] -pub trait Product: Sized { - /// Method which takes an iterator and generates `Self` from the elements by - /// multiplying the items. - #[stable(feature = "iter_arith_traits", since = "1.12.0")] - fn product>(iter: I) -> Self; -} - -// N.B., explicitly use Add and Mul here to inherit overflow checks -macro_rules! integer_sum_product { - (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($( - #[$attr] - impl Sum for $a { - fn sum>(iter: I) -> $a { - iter.fold($zero, Add::add) - } - } - - #[$attr] - impl Product for $a { - fn product>(iter: I) -> $a { - iter.fold($one, Mul::mul) - } - } - - #[$attr] - impl<'a> Sum<&'a $a> for $a { - fn sum>(iter: I) -> $a { - iter.fold($zero, Add::add) - } - } - - #[$attr] - impl<'a> Product<&'a $a> for $a { - fn product>(iter: I) -> $a { - iter.fold($one, Mul::mul) - } - } - )*); - ($($a:ty)*) => ( - integer_sum_product!(@impls 0, 1, - #[stable(feature = "iter_arith_traits", since = "1.12.0")], - $($a)+); - integer_sum_product!(@impls Wrapping(0), Wrapping(1), - #[stable(feature = "wrapping_iter_arith", since = "1.14.0")], - $(Wrapping<$a>)+); - ); -} - -macro_rules! float_sum_product { - ($($a:ident)*) => ($( - #[stable(feature = "iter_arith_traits", since = "1.12.0")] - impl Sum for $a { - fn sum>(iter: I) -> $a { - iter.fold(0.0, |a, b| a + b) - } - } - - #[stable(feature = "iter_arith_traits", since = "1.12.0")] - impl Product for $a { - fn product>(iter: I) -> $a { - iter.fold(1.0, |a, b| a * b) - } - } - - #[stable(feature = "iter_arith_traits", since = "1.12.0")] - impl<'a> Sum<&'a $a> for $a { - fn sum>(iter: I) -> $a { - iter.fold(0.0, |a, b| a + *b) - } - } - - #[stable(feature = "iter_arith_traits", since = "1.12.0")] - impl<'a> Product<&'a $a> for $a { - fn product>(iter: I) -> $a { - iter.fold(1.0, |a, b| a * *b) - } - } - )*) -} - -integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } -float_sum_product! { f32 f64 } - -/// An iterator adapter that produces output as long as the underlying -/// iterator produces `Result::Ok` values. -/// -/// If an error is encountered, the iterator stops and the error is -/// stored. The error may be recovered later via `reconstruct`. -struct ResultShunt { - iter: I, - error: Option, -} - -impl ResultShunt - where I: Iterator> -{ - /// Process the given iterator as if it yielded a `T` instead of a - /// `Result`. Any errors will stop the inner iterator and - /// the overall result will be an error. - pub fn process(iter: I, mut f: F) -> Result - where F: FnMut(&mut Self) -> U - { - let mut shunt = ResultShunt::new(iter); - let value = f(shunt.by_ref()); - shunt.reconstruct(value) - } - - fn new(iter: I) -> Self { - ResultShunt { - iter, - error: None, - } - } - - /// Consume the adapter and rebuild a `Result` value. This should - /// *always* be called, otherwise any potential error would be - /// lost. - fn reconstruct(self, val: U) -> Result { - match self.error { - None => Ok(val), - Some(e) => Err(e), - } - } -} - -impl Iterator for ResultShunt - where I: Iterator> -{ - type Item = T; - - fn next(&mut self) -> Option { - match self.iter.next() { - Some(Ok(v)) => Some(v), - Some(Err(e)) => { - self.error = Some(e); - None - } - None => None, - } - } - - fn size_hint(&self) -> (usize, Option) { - if self.error.is_some() { - (0, Some(0)) - } else { - let (_, upper) = self.iter.size_hint(); - (0, upper) - } - } -} - -#[stable(feature = "iter_arith_traits_result", since="1.16.0")] -impl Sum> for Result - where T: Sum, -{ - /// Takes each element in the `Iterator`: if it is an `Err`, no further - /// elements are taken, and the `Err` is returned. Should no `Err` occur, - /// the sum of all elements is returned. - /// - /// # Examples - /// - /// This sums up every integer in a vector, rejecting the sum if a negative - /// element is encountered: - /// - /// ``` - /// let v = vec![1, 2]; - /// let res: Result = v.iter().map(|&x: &i32| - /// if x < 0 { Err("Negative element found") } - /// else { Ok(x) } - /// ).sum(); - /// assert_eq!(res, Ok(3)); - /// ``` - fn sum(iter: I) -> Result - where I: Iterator>, - { - ResultShunt::process(iter, |i| i.sum()) - } -} - -#[stable(feature = "iter_arith_traits_result", since="1.16.0")] -impl Product> for Result - where T: Product, -{ - /// Takes each element in the `Iterator`: if it is an `Err`, no further - /// elements are taken, and the `Err` is returned. Should no `Err` occur, - /// the product of all elements is returned. - fn product(iter: I) -> Result - where I: Iterator>, - { - ResultShunt::process(iter, |i| i.product()) - } -} +pub use self::accum::{Sum, Product}; /// An iterator that always continues to yield `None` when exhausted. ///