core/iter/traits/
accum.rs

1use crate::iter;
2use crate::num::{Saturating, Wrapping};
3
4/// Trait to represent types that can be created by summing up an iterator.
5///
6/// This trait is used to implement [`Iterator::sum()`]. Types which implement
7/// this trait can be generated by using the [`sum()`] method on an iterator.
8/// Like [`FromIterator`], this trait should rarely be called directly.
9///
10/// [`sum()`]: Iterator::sum
11/// [`FromIterator`]: iter::FromIterator
12#[stable(feature = "iter_arith_traits", since = "1.12.0")]
13#[diagnostic::on_unimplemented(
14    message = "a value of type `{Self}` cannot be made by summing an iterator over elements of type `{A}`",
15    label = "value of type `{Self}` cannot be made by summing a `std::iter::Iterator<Item={A}>`"
16)]
17pub trait Sum<A = Self>: Sized {
18    /// Takes an iterator and generates `Self` from the elements by "summing up"
19    /// the items.
20    #[stable(feature = "iter_arith_traits", since = "1.12.0")]
21    fn sum<I: Iterator<Item = A>>(iter: I) -> Self;
22}
23
24/// Trait to represent types that can be created by multiplying elements of an
25/// iterator.
26///
27/// This trait is used to implement [`Iterator::product()`]. Types which implement
28/// this trait can be generated by using the [`product()`] method on an iterator.
29/// Like [`FromIterator`], this trait should rarely be called directly.
30///
31/// [`product()`]: Iterator::product
32/// [`FromIterator`]: iter::FromIterator
33#[stable(feature = "iter_arith_traits", since = "1.12.0")]
34#[diagnostic::on_unimplemented(
35    message = "a value of type `{Self}` cannot be made by multiplying all elements of type `{A}` from an iterator",
36    label = "value of type `{Self}` cannot be made by multiplying all elements from a `std::iter::Iterator<Item={A}>`"
37)]
38pub trait Product<A = Self>: Sized {
39    /// Takes an iterator and generates `Self` from the elements by multiplying
40    /// the items.
41    #[stable(feature = "iter_arith_traits", since = "1.12.0")]
42    fn product<I: Iterator<Item = A>>(iter: I) -> Self;
43}
44
45macro_rules! integer_sum_product {
46    (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($(
47        #[$attr]
48        impl Sum for $a {
49            fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
50                iter.fold(
51                    $zero,
52                    #[rustc_inherit_overflow_checks]
53                    |a, b| a + b,
54                )
55            }
56        }
57
58        #[$attr]
59        impl Product for $a {
60            fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
61                iter.fold(
62                    $one,
63                    #[rustc_inherit_overflow_checks]
64                    |a, b| a * b,
65                )
66            }
67        }
68
69        #[$attr]
70        impl<'a> Sum<&'a $a> for $a {
71            fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
72                iter.fold(
73                    $zero,
74                    #[rustc_inherit_overflow_checks]
75                    |a, b| a + b,
76                )
77            }
78        }
79
80        #[$attr]
81        impl<'a> Product<&'a $a> for $a {
82            fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
83                iter.fold(
84                    $one,
85                    #[rustc_inherit_overflow_checks]
86                    |a, b| a * b,
87                )
88            }
89        }
90    )*);
91    ($($a:ty)*) => (
92        integer_sum_product!(@impls 0, 1,
93                #[stable(feature = "iter_arith_traits", since = "1.12.0")],
94                $($a)*);
95        integer_sum_product!(@impls Wrapping(0), Wrapping(1),
96                #[stable(feature = "wrapping_iter_arith", since = "1.14.0")],
97                $(Wrapping<$a>)*);
98    );
99}
100
101macro_rules! saturating_integer_sum_product {
102    (@impls $zero:expr, $one:expr, $doc:expr, #[$attr:meta], $($a:ty)*) => ($(
103        #[$attr]
104        #[doc = $doc]
105        impl Sum for $a {
106            fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
107                iter.fold(
108                    $zero,
109                    |a, b| a + b,
110                )
111            }
112        }
113
114        #[$attr]
115        #[doc = $doc]
116        impl Product for $a {
117            fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
118                iter.fold(
119                    $one,
120                    |a, b| a * b,
121                )
122            }
123        }
124
125        #[$attr]
126        #[doc = $doc]
127        impl<'a> Sum<&'a $a> for $a {
128            fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
129                iter.fold(
130                    $zero,
131                    |a, b| a + b,
132                )
133            }
134        }
135
136        #[$attr]
137        #[doc = $doc]
138        impl<'a> Product<&'a $a> for $a {
139            fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
140                iter.fold(
141                    $one,
142                    |a, b| a * b,
143                )
144            }
145        }
146    )*);
147    ($($a:ty)*) => (
148        saturating_integer_sum_product!(@impls Saturating(0), Saturating(1),
149                "The short-circuiting behavior of this implementation is unspecified. If you care about \
150                short-circuiting, use [`Iterator::fold`] directly.",
151                #[stable(feature = "saturating_iter_arith", since = "CURRENT_RUSTC_VERSION")],
152                $(Saturating<$a>)*);
153    );
154}
155
156macro_rules! float_sum_product {
157    ($($a:ident)*) => ($(
158        #[stable(feature = "iter_arith_traits", since = "1.12.0")]
159        impl Sum for $a {
160            fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
161                iter.fold(
162                    -0.0,
163                    #[rustc_inherit_overflow_checks]
164                    |a, b| a + b,
165                )
166            }
167        }
168
169        #[stable(feature = "iter_arith_traits", since = "1.12.0")]
170        impl Product for $a {
171            fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
172                iter.fold(
173                    1.0,
174                    #[rustc_inherit_overflow_checks]
175                    |a, b| a * b,
176                )
177            }
178        }
179
180        #[stable(feature = "iter_arith_traits", since = "1.12.0")]
181        impl<'a> Sum<&'a $a> for $a {
182            fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
183                iter.fold(
184                    -0.0,
185                    #[rustc_inherit_overflow_checks]
186                    |a, b| a + b,
187                )
188            }
189        }
190
191        #[stable(feature = "iter_arith_traits", since = "1.12.0")]
192        impl<'a> Product<&'a $a> for $a {
193            fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
194                iter.fold(
195                    1.0,
196                    #[rustc_inherit_overflow_checks]
197                    |a, b| a * b,
198                )
199            }
200        }
201    )*)
202}
203
204integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
205saturating_integer_sum_product! { u8 u16 u32 u64 u128 usize }
206float_sum_product! { f32 f64 }
207
208#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
209impl<T, U, E> Sum<Result<U, E>> for Result<T, E>
210where
211    T: Sum<U>,
212{
213    /// Takes each element in the [`Iterator`]: if it is an [`Err`], no further
214    /// elements are taken, and the [`Err`] is returned. Should no [`Err`]
215    /// occur, the sum of all elements is returned.
216    ///
217    /// # Examples
218    ///
219    /// This sums up every integer in a vector, rejecting the sum if a negative
220    /// element is encountered:
221    ///
222    /// ```
223    /// let f = |&x: &i32| if x < 0 { Err("Negative element found") } else { Ok(x) };
224    /// let v = vec![1, 2];
225    /// let res: Result<i32, _> = v.iter().map(f).sum();
226    /// assert_eq!(res, Ok(3));
227    /// let v = vec![1, -2];
228    /// let res: Result<i32, _> = v.iter().map(f).sum();
229    /// assert_eq!(res, Err("Negative element found"));
230    /// ```
231    fn sum<I>(iter: I) -> Result<T, E>
232    where
233        I: Iterator<Item = Result<U, E>>,
234    {
235        iter::try_process(iter, |i| i.sum())
236    }
237}
238
239#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
240impl<T, U, E> Product<Result<U, E>> for Result<T, E>
241where
242    T: Product<U>,
243{
244    /// Takes each element in the [`Iterator`]: if it is an [`Err`], no further
245    /// elements are taken, and the [`Err`] is returned. Should no [`Err`]
246    /// occur, the product of all elements is returned.
247    ///
248    /// # Examples
249    ///
250    /// This multiplies each number in a vector of strings,
251    /// if a string could not be parsed the operation returns `Err`:
252    ///
253    /// ```
254    /// let nums = vec!["5", "10", "1", "2"];
255    /// let total: Result<usize, _> = nums.iter().map(|w| w.parse::<usize>()).product();
256    /// assert_eq!(total, Ok(100));
257    /// let nums = vec!["5", "10", "one", "2"];
258    /// let total: Result<usize, _> = nums.iter().map(|w| w.parse::<usize>()).product();
259    /// assert!(total.is_err());
260    /// ```
261    fn product<I>(iter: I) -> Result<T, E>
262    where
263        I: Iterator<Item = Result<U, E>>,
264    {
265        iter::try_process(iter, |i| i.product())
266    }
267}
268
269#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
270impl<T, U> Sum<Option<U>> for Option<T>
271where
272    T: Sum<U>,
273{
274    /// Takes each element in the [`Iterator`]: if it is a [`None`], no further
275    /// elements are taken, and the [`None`] is returned. Should no [`None`]
276    /// occur, the sum of all elements is returned.
277    ///
278    /// # Examples
279    ///
280    /// This sums up the position of the character 'a' in a vector of strings,
281    /// if a word did not have the character 'a' the operation returns `None`:
282    ///
283    /// ```
284    /// let words = vec!["have", "a", "great", "day"];
285    /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum();
286    /// assert_eq!(total, Some(5));
287    /// let words = vec!["have", "a", "good", "day"];
288    /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum();
289    /// assert_eq!(total, None);
290    /// ```
291    fn sum<I>(iter: I) -> Option<T>
292    where
293        I: Iterator<Item = Option<U>>,
294    {
295        iter::try_process(iter, |i| i.sum())
296    }
297}
298
299#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
300impl<T, U> Product<Option<U>> for Option<T>
301where
302    T: Product<U>,
303{
304    /// Takes each element in the [`Iterator`]: if it is a [`None`], no further
305    /// elements are taken, and the [`None`] is returned. Should no [`None`]
306    /// occur, the product of all elements is returned.
307    ///
308    /// # Examples
309    ///
310    /// This multiplies each number in a vector of strings,
311    /// if a string could not be parsed the operation returns `None`:
312    ///
313    /// ```
314    /// let nums = vec!["5", "10", "1", "2"];
315    /// let total: Option<usize> = nums.iter().map(|w| w.parse::<usize>().ok()).product();
316    /// assert_eq!(total, Some(100));
317    /// let nums = vec!["5", "10", "one", "2"];
318    /// let total: Option<usize> = nums.iter().map(|w| w.parse::<usize>().ok()).product();
319    /// assert_eq!(total, None);
320    /// ```
321    fn product<I>(iter: I) -> Option<T>
322    where
323        I: Iterator<Item = Option<U>>,
324    {
325        iter::try_process(iter, |i| i.product())
326    }
327}