Skip to content

Commit 4b8a918

Browse files
committed
Make sum and product inherent methods on Iterator
In addition to being nicer, this also allows you to use `sum` and `product` for iterators yielding custom types aside from the standard integers. Due to removing the `AdditiveIterator` and `MultiplicativeIterator` trait, this is a breaking change. [breaking-change]
1 parent 8842760 commit 4b8a918

File tree

10 files changed

+49
-160
lines changed

10 files changed

+49
-160
lines changed

src/libcollections/slice.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ use core::clone::Clone;
8585
use core::cmp::Ordering::{self, Greater, Less};
8686
use core::cmp::{self, Ord, PartialEq};
8787
use core::iter::Iterator;
88-
use core::iter::MultiplicativeIterator;
8988
use core::marker::Sized;
9089
use core::mem::size_of;
9190
use core::mem;
@@ -1182,7 +1181,7 @@ impl Iterator for ElementSwaps {
11821181
#[inline]
11831182
fn size_hint(&self) -> (usize, Option<usize>) {
11841183
// For a vector of size n, there are exactly n! permutations.
1185-
let n = (2..self.sdir.len() + 1).product();
1184+
let n: usize = (2..self.sdir.len() + 1).product();
11861185
(n - self.swaps_made, Some(n - self.swaps_made))
11871186
}
11881187
}

src/libcollections/str.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ use self::RecompositionState::*;
5353
use self::DecompositionType::*;
5454

5555
use core::clone::Clone;
56-
use core::iter::AdditiveIterator;
5756
use core::iter::{Iterator, Extend};
5857
use core::option::Option::{self, Some, None};
5958
use core::result::Result;
@@ -111,7 +110,7 @@ impl<S: AsRef<str>> SliceConcatExt<str, String> for [S] {
111110

112111
// this is wrong without the guarantee that `self` is non-empty
113112
// `len` calculation may overflow but push_str but will check boundaries
114-
let len = sep.len() * (self.len() - 1)
113+
let len: usize = sep.len() * (self.len() - 1)
115114
+ self.iter().map(|s| s.as_ref().len()).sum();
116115
let mut result = String::with_capacity(len);
117116
let mut first = true;

src/libcollectionstest/str.rs

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
// except according to those terms.
1010

1111
use std::cmp::Ordering::{Equal, Greater, Less};
12-
use std::iter::AdditiveIterator;
1312
use std::str::{Utf8Error, from_utf8};
1413

1514
#[test]

src/libcore/iter.rs

+42-147
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ use default::Default;
6565
use marker;
6666
use mem;
6767
use num::{Int, Zero, One};
68-
use ops::{self, Add, Sub, FnMut, RangeFrom};
68+
use ops::{self, Add, Sub, FnMut, Mul, RangeFrom};
6969
use option::Option::{self, Some, None};
7070
use marker::Sized;
7171
use usize;
@@ -489,7 +489,6 @@ pub trait Iterator {
489489
///
490490
/// ```
491491
/// # #![feature(core)]
492-
/// use std::iter::AdditiveIterator;
493492
///
494493
/// let a = [1, 4, 2, 3, 8, 9, 6];
495494
/// let sum = a.iter()
@@ -1022,6 +1021,47 @@ pub trait Iterator {
10221021
}
10231022
}
10241023
}
1024+
1025+
/// Iterates over the entire iterator, summing up all the elements
1026+
///
1027+
/// # Examples
1028+
///
1029+
/// ```
1030+
/// # #![feature(core)]
1031+
///
1032+
/// let a = [1, 2, 3, 4, 5];
1033+
/// let mut it = a.iter().cloned();
1034+
/// assert!(it.sum() == 15);
1035+
/// ```
1036+
#[unstable(feature="core")]
1037+
fn sum<S=<Self as Iterator>::Item>(self) -> S where
1038+
S: Add<Self::Item, Output=S> + Zero,
1039+
Self: Sized,
1040+
{
1041+
self.fold(Zero::zero(), |s, e| s + e)
1042+
}
1043+
1044+
/// Iterates over the entire iterator, multiplying all the elements
1045+
///
1046+
/// # Examples
1047+
///
1048+
/// ```
1049+
/// # #![feature(core)]
1050+
///
1051+
/// fn factorial(n: u32) -> u32 {
1052+
/// (1..).take_while(|&i| i <= n).product()
1053+
/// }
1054+
/// assert!(factorial(0) == 1);
1055+
/// assert!(factorial(1) == 1);
1056+
/// assert!(factorial(5) == 120);
1057+
/// ```
1058+
#[unstable(feature="core")]
1059+
fn product<P=<Self as Iterator>::Item>(self) -> P where
1060+
P: Mul<Self::Item, Output=P> + One,
1061+
Self: Sized,
1062+
{
1063+
self.fold(One::one(), |p, e| p * e)
1064+
}
10251065
}
10261066

10271067
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1222,151 +1262,6 @@ impl<I> RandomAccessIterator for Rev<I>
12221262
}
12231263
}
12241264

1225-
/// A trait for iterators over elements which can be added together
1226-
#[unstable(feature = "core",
1227-
reason = "needs to be re-evaluated as part of numerics reform")]
1228-
pub trait AdditiveIterator {
1229-
/// The result of summing over the iterator.
1230-
type SumResult;
1231-
1232-
/// Iterates over the entire iterator, summing up all the elements
1233-
///
1234-
/// # Examples
1235-
///
1236-
/// ```
1237-
/// # #![feature(core)]
1238-
/// use std::iter::AdditiveIterator;
1239-
///
1240-
/// let a = [1, 2, 3, 4, 5];
1241-
/// let mut it = a.iter().cloned();
1242-
/// assert!(it.sum() == 15);
1243-
/// ```
1244-
fn sum(self) -> Self::SumResult;
1245-
}
1246-
1247-
/// The sum operation of an iterator's item type. Implementing this allows
1248-
/// calling `.sum()` on the iterator.
1249-
#[unstable(feature = "core", reason = "trait is experimental")]
1250-
pub trait AdditiveIteratorItem {
1251-
/// The type of the intermediate sums.
1252-
type SumResult;
1253-
/// The start value of the sum, usually something like `0`.
1254-
fn start() -> Self::SumResult;
1255-
/// Adds another element of the iterator to the intermediate sum.
1256-
fn combine(self, other: Self::SumResult) -> Self::SumResult;
1257-
}
1258-
1259-
#[unstable(feature = "core", reason = "trait is experimental")]
1260-
impl<I: Iterator> AdditiveIterator for I where
1261-
<I as Iterator>::Item: AdditiveIteratorItem
1262-
{
1263-
type SumResult = <<I as Iterator>::Item as AdditiveIteratorItem>::SumResult;
1264-
fn sum(self) -> <I as AdditiveIterator>::SumResult {
1265-
let mut sum = <<I as Iterator>::Item as AdditiveIteratorItem>::start();
1266-
for x in self {
1267-
sum = x.combine(sum);
1268-
}
1269-
sum
1270-
}
1271-
}
1272-
1273-
macro_rules! impl_additive {
1274-
($T:ty, $init:expr) => {
1275-
#[unstable(feature = "core", reason = "trait is experimental")]
1276-
impl AdditiveIteratorItem for $T {
1277-
type SumResult = $T;
1278-
fn start() -> $T { $init }
1279-
fn combine(self, other: $T) -> $T { self + other }
1280-
}
1281-
};
1282-
}
1283-
impl_additive! { i8, 0 }
1284-
impl_additive! { i16, 0 }
1285-
impl_additive! { i32, 0 }
1286-
impl_additive! { i64, 0 }
1287-
impl_additive! { isize, 0 }
1288-
impl_additive! { u8, 0 }
1289-
impl_additive! { u16, 0 }
1290-
impl_additive! { u32, 0 }
1291-
impl_additive! { u64, 0 }
1292-
impl_additive! { usize, 0 }
1293-
impl_additive! { f32, 0.0 }
1294-
impl_additive! { f64, 0.0 }
1295-
1296-
/// A trait for iterators over elements which can be multiplied together.
1297-
#[unstable(feature = "core",
1298-
reason = "needs to be re-evaluated as part of numerics reform")]
1299-
pub trait MultiplicativeIterator {
1300-
/// The result of multiplying the elements of the iterator.
1301-
type ProductResult;
1302-
1303-
/// Iterates over the entire iterator, multiplying all the elements
1304-
///
1305-
/// # Examples
1306-
///
1307-
/// ```
1308-
/// # #![feature(core)]
1309-
/// use std::iter::MultiplicativeIterator;
1310-
///
1311-
/// fn factorial(n: usize) -> usize {
1312-
/// (1..).take_while(|&i| i <= n).product()
1313-
/// }
1314-
/// assert!(factorial(0) == 1);
1315-
/// assert!(factorial(1) == 1);
1316-
/// assert!(factorial(5) == 120);
1317-
/// ```
1318-
fn product(self) -> Self::ProductResult;
1319-
}
1320-
1321-
/// The product operation of an iterator's item type. Implementing this allows
1322-
/// calling `.product()` on the iterator.
1323-
#[unstable(feature = "core", reason = "trait is experimental")]
1324-
pub trait MultiplicativeIteratorItem {
1325-
/// The type of the intermediate products.
1326-
type ProductResult;
1327-
/// The start value of the product, usually something like `1`.
1328-
fn start() -> Self::ProductResult;
1329-
/// Multiplies another element of the iterator to the intermediate product.
1330-
fn combine(self, other: Self::ProductResult) -> Self::ProductResult;
1331-
}
1332-
1333-
#[unstable(feature = "core", reason = "trait is experimental")]
1334-
impl<I: Iterator> MultiplicativeIterator for I where
1335-
<I as Iterator>::Item: MultiplicativeIteratorItem
1336-
{
1337-
type ProductResult = <<I as Iterator>::Item as MultiplicativeIteratorItem>::ProductResult;
1338-
fn product(self) -> <I as MultiplicativeIterator>::ProductResult {
1339-
let mut product = <<I as Iterator>::Item as MultiplicativeIteratorItem>::start();
1340-
for x in self {
1341-
product = x.combine(product);
1342-
}
1343-
product
1344-
}
1345-
}
1346-
1347-
macro_rules! impl_multiplicative {
1348-
($T:ty, $init:expr) => {
1349-
#[unstable(feature = "core", reason = "trait is experimental")]
1350-
impl MultiplicativeIteratorItem for $T {
1351-
type ProductResult = $T;
1352-
fn start() -> $T { $init }
1353-
fn combine(self, other: $T) -> $T { self * other }
1354-
}
1355-
};
1356-
}
1357-
impl_multiplicative! { i8, 1 }
1358-
impl_multiplicative! { i16, 1 }
1359-
impl_multiplicative! { i32, 1 }
1360-
impl_multiplicative! { i64, 1 }
1361-
impl_multiplicative! { isize, 1 }
1362-
impl_multiplicative! { u8, 1 }
1363-
impl_multiplicative! { u16, 1 }
1364-
impl_multiplicative! { u32, 1 }
1365-
impl_multiplicative! { u64, 1 }
1366-
impl_multiplicative! { usize, 1 }
1367-
impl_multiplicative! { f32, 1.0 }
1368-
impl_multiplicative! { f64, 1.0 }
1369-
13701265
/// `MinMaxResult` is an enum returned by `min_max`. See `Iterator::min_max` for
13711266
/// more detail.
13721267
#[derive(Clone, PartialEq, Debug)]

src/librustc/middle/check_match.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use middle::ty::*;
2626
use middle::ty;
2727
use std::cmp::Ordering;
2828
use std::fmt;
29-
use std::iter::{range_inclusive, AdditiveIterator, FromIterator, IntoIterator, repeat};
29+
use std::iter::{range_inclusive, FromIterator, IntoIterator, repeat};
3030
use std::slice;
3131
use syntax::ast::{self, DUMMY_NODE_ID, NodeId, Pat};
3232
use syntax::ast_util;

src/librustc_trans/trans/_match.rs

-1
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,6 @@ use util::ppaux::{Repr, vec_map_to_string};
220220

221221
use std;
222222
use std::cmp::Ordering;
223-
use std::iter::AdditiveIterator;
224223
use std::rc::Rc;
225224
use syntax::ast;
226225
use syntax::ast::{DUMMY_NODE_ID, Ident, NodeId};

src/librustc_typeck/astconv.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
6161
use util::common::{ErrorReported, FN_OUTPUT_NAME};
6262
use util::ppaux::{self, Repr, UserString};
6363

64-
use std::iter::{repeat, AdditiveIterator};
64+
use std::iter::repeat;
6565
use std::rc::Rc;
6666
use std::slice;
6767
use syntax::{abi, ast, ast_util};

src/libstd/old_path/posix.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd};
1515
use fmt;
1616
use hash;
1717
use old_io::Writer;
18-
use iter::{AdditiveIterator, Extend};
19-
use iter::{Iterator, Map};
18+
use iter::{Extend, Iterator, Map};
2019
use marker::Sized;
2120
use option::Option::{self, Some, None};
2221
use result::Result::{self, Ok, Err};

src/libstd/old_path/windows.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd};
2020
use fmt;
2121
use hash;
2222
use old_io::Writer;
23-
use iter::{AdditiveIterator, Extend};
24-
use iter::{Iterator, Map, repeat};
23+
use iter::{Extend, Iterator, Map, repeat};
2524
use mem;
2625
use option::Option::{self, Some, None};
2726
use result::Result::{self, Ok, Err};

src/libunicode/u_str.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use core::prelude::*;
2020

2121
use core::char;
2222
use core::cmp;
23-
use core::iter::{Filter, AdditiveIterator};
23+
use core::iter::Filter;
2424
use core::mem;
2525
use core::slice;
2626
use core::str::Split;

0 commit comments

Comments
 (0)