accum.rs - source
Description: Source of the Rust file `library/core/src/iter/traits/accum.rs`.

#
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 = "1.91.0")],
    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! { f16 f32 f64 f128 }
    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}