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