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 [`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.
10 /// [`sum()`]: Iterator::sum
11 /// [`FromIterator`]: iter::FromIterator
12 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
13 #[rustc_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}>`"
17 pub trait Sum<A = Self>: Sized {
18 /// Method which takes an iterator and generates `Self` from the elements by
19 /// "summing up" the items.
20 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
21 fn sum<I: Iterator<Item = A>>(iter: I) -> Self;
24 /// Trait to represent types that can be created by multiplying elements of an
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.
31 /// [`product()`]: Iterator::product
32 /// [`FromIterator`]: iter::FromIterator
33 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
34 #[rustc_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}>`"
38 pub trait Product<A = Self>: Sized {
39 /// Method which takes an iterator and generates `Self` from the elements by
40 /// multiplying the items.
41 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
42 fn product<I: Iterator<Item = A>>(iter: I) -> Self;
45 macro_rules! integer_sum_product {
46 (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($(
49 fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
52 #[rustc_inherit_overflow_checks]
60 fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
63 #[rustc_inherit_overflow_checks]
70 impl<'a> Sum<&'a $a> for $a {
71 fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
74 #[rustc_inherit_overflow_checks]
81 impl<'a> Product<&'a $a> for $a {
82 fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
85 #[rustc_inherit_overflow_checks]
92 integer_sum_product!(@impls 0, 1,
93 #[stable(feature = "iter_arith_traits", since = "1.12.0")],
95 integer_sum_product!(@impls Wrapping(0), Wrapping(1),
96 #[stable(feature = "wrapping_iter_arith", since = "1.14.0")],
101 macro_rules! float_sum_product {
102 ($($a:ident)*) => ($(
103 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
105 fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
108 #[rustc_inherit_overflow_checks]
114 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
115 impl Product for $a {
116 fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
119 #[rustc_inherit_overflow_checks]
125 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
126 impl<'a> Sum<&'a $a> for $a {
127 fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
130 #[rustc_inherit_overflow_checks]
136 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
137 impl<'a> Product<&'a $a> for $a {
138 fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
141 #[rustc_inherit_overflow_checks]
149 integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
150 float_sum_product! { f32 f64 }
152 #[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
153 impl<T, U, E> Sum<Result<U, E>> for Result<T, E>
157 /// Takes each element in the [`Iterator`]: if it is an [`Err`], no further
158 /// elements are taken, and the [`Err`] is returned. Should no [`Err`]
159 /// occur, the sum of all elements is returned.
163 /// This sums up every integer in a vector, rejecting the sum if a negative
164 /// element is encountered:
167 /// let v = vec![1, 2];
168 /// let res: Result<i32, &'static str> = v.iter().map(|&x: &i32|
169 /// if x < 0 { Err("Negative element found") }
172 /// assert_eq!(res, Ok(3));
174 fn sum<I>(iter: I) -> Result<T, E>
176 I: Iterator<Item = Result<U, E>>,
178 iter::try_process(iter, |i| i.sum())
182 #[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
183 impl<T, U, E> Product<Result<U, E>> for Result<T, E>
187 /// Takes each element in the [`Iterator`]: if it is an [`Err`], no further
188 /// elements are taken, and the [`Err`] is returned. Should no [`Err`]
189 /// occur, the product of all elements is returned.
190 fn product<I>(iter: I) -> Result<T, E>
192 I: Iterator<Item = Result<U, E>>,
194 iter::try_process(iter, |i| i.product())
198 #[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
199 impl<T, U> Sum<Option<U>> for Option<T>
203 /// Takes each element in the [`Iterator`]: if it is a [`None`], no further
204 /// elements are taken, and the [`None`] is returned. Should no [`None`]
205 /// occur, the sum of all elements is returned.
209 /// This sums up the position of the character 'a' in a vector of strings,
210 /// if a word did not have the character 'a' the operation returns `None`:
213 /// let words = vec!["have", "a", "great", "day"];
214 /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum();
215 /// assert_eq!(total, Some(5));
217 fn sum<I>(iter: I) -> Option<T>
219 I: Iterator<Item = Option<U>>,
221 iter::try_process(iter, |i| i.sum())
225 #[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
226 impl<T, U> Product<Option<U>> for Option<T>
230 /// Takes each element in the [`Iterator`]: if it is a [`None`], no further
231 /// elements are taken, and the [`None`] is returned. Should no [`None`]
232 /// occur, the product of all elements is returned.
233 fn product<I>(iter: I) -> Option<T>
235 I: Iterator<Item = Option<U>>,
237 iter::try_process(iter, |i| i.product())