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}