2 use crate::num
::Wrapping
;
3 use crate::ops
::{Add, Mul}
;
5 /// Trait to represent types that can be created by summing up an iterator.
7 /// This trait is used to implement the [`sum`] method on iterators. Types which
8 /// implement the trait can be generated by the [`sum`] method. Like
9 /// [`FromIterator`] this trait should rarely be called directly and instead
10 /// interacted with through [`Iterator::sum`].
12 /// [`sum`]: ../../std/iter/trait.Sum.html#tymethod.sum
13 /// [`FromIterator`]: ../../std/iter/trait.FromIterator.html
14 /// [`Iterator::sum`]: ../../std/iter/trait.Iterator.html#method.sum
15 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
16 pub trait Sum
<A
= Self>: Sized
{
17 /// Method which takes an iterator and generates `Self` from the elements by
18 /// "summing up" the items.
19 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
20 fn sum
<I
: Iterator
<Item
= A
>>(iter
: I
) -> Self;
23 /// Trait to represent types that can be created by multiplying elements of an
26 /// This trait is used to implement the [`product`] method on iterators. Types
27 /// which implement the trait can be generated by the [`product`] method. Like
28 /// [`FromIterator`] this trait should rarely be called directly and instead
29 /// interacted with through [`Iterator::product`].
31 /// [`product`]: ../../std/iter/trait.Product.html#tymethod.product
32 /// [`FromIterator`]: ../../std/iter/trait.FromIterator.html
33 /// [`Iterator::product`]: ../../std/iter/trait.Iterator.html#method.product
34 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
35 pub trait Product
<A
= Self>: Sized
{
36 /// Method which takes an iterator and generates `Self` from the elements by
37 /// multiplying the items.
38 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
39 fn product
<I
: Iterator
<Item
= A
>>(iter
: I
) -> Self;
42 // N.B., explicitly use Add and Mul here to inherit overflow checks
43 macro_rules
! integer_sum_product
{
44 (@impls $zero
:expr
, $one
:expr
, #[$attr:meta], $($a:ty)*) => ($(
47 fn sum
<I
: Iterator
<Item
=Self>>(iter
: I
) -> Self {
48 iter
.fold($zero
, Add
::add
)
54 fn product
<I
: Iterator
<Item
=Self>>(iter
: I
) -> Self {
55 iter
.fold($one
, Mul
::mul
)
60 impl<'a
> Sum
<&'a $a
> for $a
{
61 fn sum
<I
: Iterator
<Item
=&'a
Self>>(iter
: I
) -> Self {
62 iter
.fold($zero
, Add
::add
)
67 impl<'a
> Product
<&'a $a
> for $a
{
68 fn product
<I
: Iterator
<Item
=&'a
Self>>(iter
: I
) -> Self {
69 iter
.fold($one
, Mul
::mul
)
74 integer_sum_product
!(@impls
0, 1,
75 #[stable(feature = "iter_arith_traits", since = "1.12.0")],
77 integer_sum_product
!(@impls
Wrapping(0), Wrapping(1),
78 #[stable(feature = "wrapping_iter_arith", since = "1.14.0")],
83 macro_rules
! float_sum_product
{
85 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
87 fn sum
<I
: Iterator
<Item
=Self>>(iter
: I
) -> Self {
88 iter
.fold(0.0, Add
::add
)
92 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
94 fn product
<I
: Iterator
<Item
=Self>>(iter
: I
) -> Self {
95 iter
.fold(1.0, Mul
::mul
)
99 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
100 impl<'a
> Sum
<&'a $a
> for $a
{
101 fn sum
<I
: Iterator
<Item
=&'a
Self>>(iter
: I
) -> Self {
102 iter
.fold(0.0, Add
::add
)
106 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
107 impl<'a
> Product
<&'a $a
> for $a
{
108 fn product
<I
: Iterator
<Item
=&'a
Self>>(iter
: I
) -> Self {
109 iter
.fold(1.0, Mul
::mul
)
115 integer_sum_product
! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
116 float_sum_product
! { f32 f64 }
118 #[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
119 impl<T
, U
, E
> Sum
<Result
<U
, E
>> for Result
<T
, E
>
123 /// Takes each element in the `Iterator`: if it is an `Err`, no further
124 /// elements are taken, and the `Err` is returned. Should no `Err` occur,
125 /// the sum of all elements is returned.
129 /// This sums up every integer in a vector, rejecting the sum if a negative
130 /// element is encountered:
133 /// let v = vec![1, 2];
134 /// let res: Result<i32, &'static str> = v.iter().map(|&x: &i32|
135 /// if x < 0 { Err("Negative element found") }
138 /// assert_eq!(res, Ok(3));
140 fn sum
<I
>(iter
: I
) -> Result
<T
, E
>
142 I
: Iterator
<Item
= Result
<U
, E
>>,
144 iter
::process_results(iter
, |i
| i
.sum())
148 #[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
149 impl<T
, U
, E
> Product
<Result
<U
, E
>> for Result
<T
, E
>
153 /// Takes each element in the `Iterator`: if it is an `Err`, no further
154 /// elements are taken, and the `Err` is returned. Should no `Err` occur,
155 /// the product of all elements is returned.
156 fn product
<I
>(iter
: I
) -> Result
<T
, E
>
158 I
: Iterator
<Item
= Result
<U
, E
>>,
160 iter
::process_results(iter
, |i
| i
.product())
164 #[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
165 impl<T
, U
> Sum
<Option
<U
>> for Option
<T
>
169 /// Takes each element in the `Iterator`: if it is a `None`, no further
170 /// elements are taken, and the `None` is returned. Should no `None` occur,
171 /// the sum of all elements is returned.
175 /// This sums up the position of the character 'a' in a vector of strings,
176 /// if a word did not have the character 'a' the operation returns `None`:
179 /// let words = vec!["have", "a", "great", "day"];
180 /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum();
181 /// assert_eq!(total, Some(5));
183 fn sum
<I
>(iter
: I
) -> Option
<T
>
185 I
: Iterator
<Item
= Option
<U
>>,
187 iter
.map(|x
| x
.ok_or(())).sum
::<Result
<_
, _
>>().ok()
191 #[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
192 impl<T
, U
> Product
<Option
<U
>> for Option
<T
>
196 /// Takes each element in the `Iterator`: if it is a `None`, no further
197 /// elements are taken, and the `None` is returned. Should no `None` occur,
198 /// the product of all elements is returned.
199 fn product
<I
>(iter
: I
) -> Option
<T
>
201 I
: Iterator
<Item
= Option
<U
>>,
203 iter
.map(|x
| x
.ok_or(())).product
::<Result
<_
, _
>>().ok()