Move Sum, Product to own module
This commit is contained in:
parent
3ba9733d71
commit
4a036142a0
2 changed files with 227 additions and 226 deletions
225
src/libcore/iter/traits/accum.rs
Normal file
225
src/libcore/iter/traits/accum.rs
Normal file
|
|
@ -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<A = Self>: 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<I: Iterator<Item=A>>(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<A = Self>: 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<I: Iterator<Item=A>>(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<I: Iterator<Item=$a>>(iter: I) -> $a {
|
||||
iter.fold($zero, Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
#[$attr]
|
||||
impl Product for $a {
|
||||
fn product<I: Iterator<Item=$a>>(iter: I) -> $a {
|
||||
iter.fold($one, Mul::mul)
|
||||
}
|
||||
}
|
||||
|
||||
#[$attr]
|
||||
impl<'a> Sum<&'a $a> for $a {
|
||||
fn sum<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
|
||||
iter.fold($zero, Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
#[$attr]
|
||||
impl<'a> Product<&'a $a> for $a {
|
||||
fn product<I: Iterator<Item=&'a $a>>(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<I: Iterator<Item=$a>>(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<I: Iterator<Item=$a>>(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<I: Iterator<Item=&'a $a>>(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<I: Iterator<Item=&'a $a>>(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<I, E> {
|
||||
iter: I,
|
||||
error: Option<E>,
|
||||
}
|
||||
|
||||
impl<I, T, E> ResultShunt<I, E>
|
||||
where I: Iterator<Item = Result<T, E>>
|
||||
{
|
||||
/// Process the given iterator as if it yielded a `T` instead of a
|
||||
/// `Result<T, _>`. Any errors will stop the inner iterator and
|
||||
/// the overall result will be an error.
|
||||
pub fn process<F, U>(iter: I, mut f: F) -> Result<U, E>
|
||||
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<U>(self, val: U) -> Result<U, E> {
|
||||
match self.error {
|
||||
None => Ok(val),
|
||||
Some(e) => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, T, E> Iterator for ResultShunt<I, E>
|
||||
where I: Iterator<Item = Result<T, E>>
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
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<usize>) {
|
||||
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<T, U, E> Sum<Result<U, E>> for Result<T, E>
|
||||
where T: Sum<U>,
|
||||
{
|
||||
/// 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<i32, &'static str> = v.iter().map(|&x: &i32|
|
||||
/// if x < 0 { Err("Negative element found") }
|
||||
/// else { Ok(x) }
|
||||
/// ).sum();
|
||||
/// assert_eq!(res, Ok(3));
|
||||
/// ```
|
||||
fn sum<I>(iter: I) -> Result<T, E>
|
||||
where I: Iterator<Item = Result<U, E>>,
|
||||
{
|
||||
ResultShunt::process(iter, |i| i.sum())
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_arith_traits_result", since="1.16.0")]
|
||||
impl<T, U, E> Product<Result<U, E>> for Result<T, E>
|
||||
where T: Product<U>,
|
||||
{
|
||||
/// 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<I>(iter: I) -> Result<T, E>
|
||||
where I: Iterator<Item = Result<U, E>>,
|
||||
{
|
||||
ResultShunt::process(iter, |i| i.product())
|
||||
}
|
||||
}
|
||||
|
|
@ -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<A = Self>: 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<I: Iterator<Item=A>>(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<A = Self>: 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<I: Iterator<Item=A>>(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<I: Iterator<Item=$a>>(iter: I) -> $a {
|
||||
iter.fold($zero, Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
#[$attr]
|
||||
impl Product for $a {
|
||||
fn product<I: Iterator<Item=$a>>(iter: I) -> $a {
|
||||
iter.fold($one, Mul::mul)
|
||||
}
|
||||
}
|
||||
|
||||
#[$attr]
|
||||
impl<'a> Sum<&'a $a> for $a {
|
||||
fn sum<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
|
||||
iter.fold($zero, Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
#[$attr]
|
||||
impl<'a> Product<&'a $a> for $a {
|
||||
fn product<I: Iterator<Item=&'a $a>>(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<I: Iterator<Item=$a>>(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<I: Iterator<Item=$a>>(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<I: Iterator<Item=&'a $a>>(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<I: Iterator<Item=&'a $a>>(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<I, E> {
|
||||
iter: I,
|
||||
error: Option<E>,
|
||||
}
|
||||
|
||||
impl<I, T, E> ResultShunt<I, E>
|
||||
where I: Iterator<Item = Result<T, E>>
|
||||
{
|
||||
/// Process the given iterator as if it yielded a `T` instead of a
|
||||
/// `Result<T, _>`. Any errors will stop the inner iterator and
|
||||
/// the overall result will be an error.
|
||||
pub fn process<F, U>(iter: I, mut f: F) -> Result<U, E>
|
||||
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<U>(self, val: U) -> Result<U, E> {
|
||||
match self.error {
|
||||
None => Ok(val),
|
||||
Some(e) => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, T, E> Iterator for ResultShunt<I, E>
|
||||
where I: Iterator<Item = Result<T, E>>
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
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<usize>) {
|
||||
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<T, U, E> Sum<Result<U, E>> for Result<T, E>
|
||||
where T: Sum<U>,
|
||||
{
|
||||
/// 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<i32, &'static str> = v.iter().map(|&x: &i32|
|
||||
/// if x < 0 { Err("Negative element found") }
|
||||
/// else { Ok(x) }
|
||||
/// ).sum();
|
||||
/// assert_eq!(res, Ok(3));
|
||||
/// ```
|
||||
fn sum<I>(iter: I) -> Result<T, E>
|
||||
where I: Iterator<Item = Result<U, E>>,
|
||||
{
|
||||
ResultShunt::process(iter, |i| i.sum())
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_arith_traits_result", since="1.16.0")]
|
||||
impl<T, U, E> Product<Result<U, E>> for Result<T, E>
|
||||
where T: Product<U>,
|
||||
{
|
||||
/// 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<I>(iter: I) -> Result<T, E>
|
||||
where I: Iterator<Item = Result<U, E>>,
|
||||
{
|
||||
ResultShunt::process(iter, |i| i.product())
|
||||
}
|
||||
}
|
||||
pub use self::accum::{Sum, Product};
|
||||
|
||||
/// An iterator that always continues to yield `None` when exhausted.
|
||||
///
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue