core/iter/traits/
accum.rs

1use crate::iter;
2use crate::num::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! float_sum_product {
102    ($($a:ident)*) => ($(
103        #[stable(feature = "iter_arith_traits", since = "1.12.0")]
104        impl Sum for $a {
105            fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
106                iter.fold(
107                    -0.0,
108                    #[rustc_inherit_overflow_checks]
109                    |a, b| a + b,
110                )
111            }
112        }
113
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 {
117                iter.fold(
118                    1.0,
119                    #[rustc_inherit_overflow_checks]
120                    |a, b| a * b,
121                )
122            }
123        }
124
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 {
128                iter.fold(
129                    -0.0,
130                    #[rustc_inherit_overflow_checks]
131                    |a, b| a + b,
132                )
133            }
134        }
135
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 {
139                iter.fold(
140                    1.0,
141                    #[rustc_inherit_overflow_checks]
142                    |a, b| a * b,
143                )
144            }
145        }
146    )*)
147}
148
149integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
150float_sum_product! { f32 f64 }
151
152#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
153impl<T, U, E> Sum<Result<U, E>> for Result<T, E>
154where
155    T: Sum<U>,
156{
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.
160    ///
161    /// # Examples
162    ///
163    /// This sums up every integer in a vector, rejecting the sum if a negative
164    /// element is encountered:
165    ///
166    /// ```
167    /// let f = |&x: &i32| if x < 0 { Err("Negative element found") } else { Ok(x) };
168    /// let v = vec![1, 2];
169    /// let res: Result<i32, _> = v.iter().map(f).sum();
170    /// assert_eq!(res, Ok(3));
171    /// let v = vec![1, -2];
172    /// let res: Result<i32, _> = v.iter().map(f).sum();
173    /// assert_eq!(res, Err("Negative element found"));
174    /// ```
175    fn sum<I>(iter: I) -> Result<T, E>
176    where
177        I: Iterator<Item = Result<U, E>>,
178    {
179        iter::try_process(iter, |i| i.sum())
180    }
181}
182
183#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
184impl<T, U, E> Product<Result<U, E>> for Result<T, E>
185where
186    T: Product<U>,
187{
188    /// Takes each element in the [`Iterator`]: if it is an [`Err`], no further
189    /// elements are taken, and the [`Err`] is returned. Should no [`Err`]
190    /// occur, the product of all elements is returned.
191    ///
192    /// # Examples
193    ///
194    /// This multiplies each number in a vector of strings,
195    /// if a string could not be parsed the operation returns `Err`:
196    ///
197    /// ```
198    /// let nums = vec!["5", "10", "1", "2"];
199    /// let total: Result<usize, _> = nums.iter().map(|w| w.parse::<usize>()).product();
200    /// assert_eq!(total, Ok(100));
201    /// let nums = vec!["5", "10", "one", "2"];
202    /// let total: Result<usize, _> = nums.iter().map(|w| w.parse::<usize>()).product();
203    /// assert!(total.is_err());
204    /// ```
205    fn product<I>(iter: I) -> Result<T, E>
206    where
207        I: Iterator<Item = Result<U, E>>,
208    {
209        iter::try_process(iter, |i| i.product())
210    }
211}
212
213#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
214impl<T, U> Sum<Option<U>> for Option<T>
215where
216    T: Sum<U>,
217{
218    /// Takes each element in the [`Iterator`]: if it is a [`None`], no further
219    /// elements are taken, and the [`None`] is returned. Should no [`None`]
220    /// occur, the sum of all elements is returned.
221    ///
222    /// # Examples
223    ///
224    /// This sums up the position of the character 'a' in a vector of strings,
225    /// if a word did not have the character 'a' the operation returns `None`:
226    ///
227    /// ```
228    /// let words = vec!["have", "a", "great", "day"];
229    /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum();
230    /// assert_eq!(total, Some(5));
231    /// let words = vec!["have", "a", "good", "day"];
232    /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum();
233    /// assert_eq!(total, None);
234    /// ```
235    fn sum<I>(iter: I) -> Option<T>
236    where
237        I: Iterator<Item = Option<U>>,
238    {
239        iter::try_process(iter, |i| i.sum())
240    }
241}
242
243#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
244impl<T, U> Product<Option<U>> for Option<T>
245where
246    T: Product<U>,
247{
248    /// Takes each element in the [`Iterator`]: if it is a [`None`], no further
249    /// elements are taken, and the [`None`] is returned. Should no [`None`]
250    /// occur, the product of all elements is returned.
251    ///
252    /// # Examples
253    ///
254    /// This multiplies each number in a vector of strings,
255    /// if a string could not be parsed the operation returns `None`:
256    ///
257    /// ```
258    /// let nums = vec!["5", "10", "1", "2"];
259    /// let total: Option<usize> = nums.iter().map(|w| w.parse::<usize>().ok()).product();
260    /// assert_eq!(total, Some(100));
261    /// let nums = vec!["5", "10", "one", "2"];
262    /// let total: Option<usize> = nums.iter().map(|w| w.parse::<usize>().ok()).product();
263    /// assert_eq!(total, None);
264    /// ```
265    fn product<I>(iter: I) -> Option<T>
266    where
267        I: Iterator<Item = Option<U>>,
268    {
269        iter::try_process(iter, |i| i.product())
270    }
271}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy