1 use crate::ops::{Mul, Add};
2 use crate::num::Wrapping;
4 /// Trait to represent types that can be created by summing up an iterator.
6 /// This trait is used to implement the [`sum`] method on iterators. Types which
7 /// implement the trait can be generated by the [`sum`] method. Like
8 /// [`FromIterator`] this trait should rarely be called directly and instead
9 /// interacted with through [`Iterator::sum`].
11 /// [`sum`]: ../../std/iter/trait.Sum.html#tymethod.sum
12 /// [`FromIterator`]: ../../std/iter/trait.FromIterator.html
13 /// [`Iterator::sum`]: ../../std/iter/trait.Iterator.html#method.sum
14 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
15 pub trait Sum<A = Self>: Sized {
16 /// Method which takes an iterator and generates `Self` from the elements by
17 /// "summing up" the items.
18 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
19 fn sum<I: Iterator<Item=A>>(iter: I) -> Self;
22 /// Trait to represent types that can be created by multiplying elements of an
25 /// This trait is used to implement the [`product`] method on iterators. Types
26 /// which implement the trait can be generated by the [`product`] method. Like
27 /// [`FromIterator`] this trait should rarely be called directly and instead
28 /// interacted with through [`Iterator::product`].
30 /// [`product`]: ../../std/iter/trait.Product.html#tymethod.product
31 /// [`FromIterator`]: ../../std/iter/trait.FromIterator.html
32 /// [`Iterator::product`]: ../../std/iter/trait.Iterator.html#method.product
33 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
34 pub trait Product<A = Self>: Sized {
35 /// Method which takes an iterator and generates `Self` from the elements by
36 /// multiplying the items.
37 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
38 fn product<I: Iterator<Item=A>>(iter: I) -> Self;
41 // N.B., explicitly use Add and Mul here to inherit overflow checks
42 macro_rules! integer_sum_product {
43 (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($(
46 fn sum<I: Iterator<Item=$a>>(iter: I) -> $a {
47 iter.fold($zero, Add::add)
53 fn product<I: Iterator<Item=$a>>(iter: I) -> $a {
54 iter.fold($one, Mul::mul)
59 impl<'a> Sum<&'a $a> for $a {
60 fn sum<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
61 iter.fold($zero, Add::add)
66 impl<'a> Product<&'a $a> for $a {
67 fn product<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
68 iter.fold($one, Mul::mul)
73 integer_sum_product!(@impls 0, 1,
74 #[stable(feature = "iter_arith_traits", since = "1.12.0")],
76 integer_sum_product!(@impls Wrapping(0), Wrapping(1),
77 #[stable(feature = "wrapping_iter_arith", since = "1.14.0")],
82 macro_rules! float_sum_product {
84 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
86 fn sum<I: Iterator<Item=$a>>(iter: I) -> $a {
87 iter.fold(0.0, |a, b| a + b)
91 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
93 fn product<I: Iterator<Item=$a>>(iter: I) -> $a {
94 iter.fold(1.0, |a, b| a * b)
98 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
99 impl<'a> Sum<&'a $a> for $a {
100 fn sum<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
101 iter.fold(0.0, |a, b| a + *b)
105 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
106 impl<'a> Product<&'a $a> for $a {
107 fn product<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
108 iter.fold(1.0, |a, b| a * *b)
114 integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
115 float_sum_product! { f32 f64 }
117 /// An iterator adapter that produces output as long as the underlying
118 /// iterator produces `Result::Ok` values.
120 /// If an error is encountered, the iterator stops and the error is
121 /// stored. The error may be recovered later via `reconstruct`.
122 struct ResultShunt<I, E> {
127 impl<I, T, E> ResultShunt<I, E>
128 where I: Iterator<Item = Result<T, E>>
130 /// Process the given iterator as if it yielded a `T` instead of a
131 /// `Result<T, _>`. Any errors will stop the inner iterator and
132 /// the overall result will be an error.
133 pub fn process<F, U>(iter: I, mut f: F) -> Result<U, E>
134 where F: FnMut(&mut Self) -> U
136 let mut shunt = ResultShunt::new(iter);
137 let value = f(shunt.by_ref());
138 shunt.reconstruct(value)
141 fn new(iter: I) -> Self {
148 /// Consume the adapter and rebuild a `Result` value. This should
149 /// *always* be called, otherwise any potential error would be
151 fn reconstruct<U>(self, val: U) -> Result<U, E> {
159 impl<I, T, E> Iterator for ResultShunt<I, E>
160 where I: Iterator<Item = Result<T, E>>
164 fn next(&mut self) -> Option<Self::Item> {
165 match self.iter.next() {
166 Some(Ok(v)) => Some(v),
168 self.error = Some(e);
175 fn size_hint(&self) -> (usize, Option<usize>) {
176 if self.error.is_some() {
179 let (_, upper) = self.iter.size_hint();
185 #[stable(feature = "iter_arith_traits_result", since="1.16.0")]
186 impl<T, U, E> Sum<Result<U, E>> for Result<T, E>
189 /// Takes each element in the `Iterator`: if it is an `Err`, no further
190 /// elements are taken, and the `Err` is returned. Should no `Err` occur,
191 /// the sum of all elements is returned.
195 /// This sums up every integer in a vector, rejecting the sum if a negative
196 /// element is encountered:
199 /// let v = vec![1, 2];
200 /// let res: Result<i32, &'static str> = v.iter().map(|&x: &i32|
201 /// if x < 0 { Err("Negative element found") }
204 /// assert_eq!(res, Ok(3));
206 fn sum<I>(iter: I) -> Result<T, E>
207 where I: Iterator<Item = Result<U, E>>,
209 ResultShunt::process(iter, |i| i.sum())
213 #[stable(feature = "iter_arith_traits_result", since="1.16.0")]
214 impl<T, U, E> Product<Result<U, E>> for Result<T, E>
217 /// Takes each element in the `Iterator`: if it is an `Err`, no further
218 /// elements are taken, and the `Err` is returned. Should no `Err` occur,
219 /// the product of all elements is returned.
220 fn product<I>(iter: I) -> Result<T, E>
221 where I: Iterator<Item = Result<U, E>>,
223 ResultShunt::process(iter, |i| i.product())
227 /// An iterator adapter that produces output as long as the underlying
228 /// iterator produces `Option::Some` values.
229 struct OptionShunt<I> {
234 impl<I, T> OptionShunt<I>
236 I: Iterator<Item = Option<T>>,
238 /// Process the given iterator as if it yielded a `T` instead of a
239 /// `Option<T>`. Any `None` value will stop the inner iterator and
240 /// the overall result will be a `None`.
241 pub fn process<F, U>(iter: I, mut f: F) -> Option<U>
243 F: FnMut(&mut Self) -> U,
245 let mut shunt = OptionShunt::new(iter);
246 let value = f(shunt.by_ref());
247 shunt.reconstruct(value)
250 fn new(iter: I) -> Self {
257 /// Consume the adapter and rebuild a `Option` value.
258 fn reconstruct<U>(self, val: U) -> Option<U> {
259 if self.exited_early {
267 impl<I, T> Iterator for OptionShunt<I>
269 I: Iterator<Item = Option<T>>,
273 fn next(&mut self) -> Option<Self::Item> {
274 match self.iter.next() {
275 Some(Some(v)) => Some(v),
277 self.exited_early = true;
284 fn size_hint(&self) -> (usize, Option<usize>) {
285 if self.exited_early {
288 let (_, upper) = self.iter.size_hint();
294 #[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
295 impl<T, U> Sum<Option<U>> for Option<T>
299 /// Takes each element in the `Iterator`: if it is a `None`, no further
300 /// elements are taken, and the `None` is returned. Should no `None` occur,
301 /// the sum of all elements is returned.
305 /// This sums up the position of the character 'a' in a vector of strings,
306 /// if a word did not have the character 'a' the operation returns `None`:
309 /// let words = vec!["have", "a", "great", "day"];
310 /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum();
311 /// assert_eq!(total, Some(5));
313 fn sum<I>(iter: I) -> Option<T>
315 I: Iterator<Item = Option<U>>,
317 OptionShunt::process(iter, |i| i.sum())
321 #[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
322 impl<T, U> Product<Option<U>> for Option<T>
326 /// Takes each element in the `Iterator`: if it is a `None`, no further
327 /// elements are taken, and the `None` is returned. Should no `None` occur,
328 /// the product of all elements is returned.
329 fn product<I>(iter: I) -> Option<T>
331 I: Iterator<Item = Option<U>>,
333 OptionShunt::process(iter, |i| i.product())