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 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"));
175 fn sum
<I
>(iter
: I
) -> Result
<T
, E
>
177 I
: Iterator
<Item
= Result
<U
, E
>>,
179 iter
::try_process(iter
, |i
| i
.sum())
183 #[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
184 impl<T
, U
, E
> Product
<Result
<U
, E
>> for Result
<T
, E
>
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.
194 /// This multiplies each number in a vector of strings,
195 /// if a string could not be parsed the operation returns `Err`:
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());
205 fn product
<I
>(iter
: I
) -> Result
<T
, E
>
207 I
: Iterator
<Item
= Result
<U
, E
>>,
209 iter
::try_process(iter
, |i
| i
.product())
213 #[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
214 impl<T
, U
> Sum
<Option
<U
>> for Option
<T
>
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.
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`:
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);
235 fn sum
<I
>(iter
: I
) -> Option
<T
>
237 I
: Iterator
<Item
= Option
<U
>>,
239 iter
::try_process(iter
, |i
| i
.sum())
243 #[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
244 impl<T
, U
> Product
<Option
<U
>> for Option
<T
>
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.
254 /// This multiplies each number in a vector of strings,
255 /// if a string could not be parsed the operation returns `None`:
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);
265 fn product
<I
>(iter
: I
) -> Option
<T
>
267 I
: Iterator
<Item
= Option
<U
>>,
269 iter
::try_process(iter
, |i
| i
.product())