Skip to content

Commit 8842760

Browse files
committed
Make AdditiveIterator and MultiplicativeIterator extensible
Previously it could not be implemented for types outside `libcore/iter.rs` due to coherence issues.
1 parent cf51e55 commit 8842760

File tree

1 file changed

+93
-37
lines changed

1 file changed

+93
-37
lines changed

src/libcore/iter.rs

Lines changed: 93 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,7 +1225,10 @@ impl<I> RandomAccessIterator for Rev<I>
12251225
/// A trait for iterators over elements which can be added together
12261226
#[unstable(feature = "core",
12271227
reason = "needs to be re-evaluated as part of numerics reform")]
1228-
pub trait AdditiveIterator<A> {
1228+
pub trait AdditiveIterator {
1229+
/// The result of summing over the iterator.
1230+
type SumResult;
1231+
12291232
/// Iterates over the entire iterator, summing up all the elements
12301233
///
12311234
/// # Examples
@@ -1238,37 +1241,65 @@ pub trait AdditiveIterator<A> {
12381241
/// let mut it = a.iter().cloned();
12391242
/// assert!(it.sum() == 15);
12401243
/// ```
1241-
fn sum(self) -> A;
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+
}
12421271
}
12431272

12441273
macro_rules! impl_additive {
1245-
($A:ty, $init:expr) => {
1274+
($T:ty, $init:expr) => {
12461275
#[unstable(feature = "core", reason = "trait is experimental")]
1247-
impl<T: Iterator<Item=$A>> AdditiveIterator<$A> for T {
1248-
#[inline]
1249-
fn sum(self) -> $A {
1250-
self.fold($init, |acc, x| acc + x)
1251-
}
1276+
impl AdditiveIteratorItem for $T {
1277+
type SumResult = $T;
1278+
fn start() -> $T { $init }
1279+
fn combine(self, other: $T) -> $T { self + other }
12521280
}
12531281
};
12541282
}
1255-
impl_additive! { i8, 0 }
1256-
impl_additive! { i16, 0 }
1257-
impl_additive! { i32, 0 }
1258-
impl_additive! { i64, 0 }
1259-
impl_additive! { isize, 0 }
1260-
impl_additive! { u8, 0 }
1261-
impl_additive! { u16, 0 }
1262-
impl_additive! { u32, 0 }
1263-
impl_additive! { u64, 0 }
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 }
12641292
impl_additive! { usize, 0 }
1265-
impl_additive! { f32, 0.0 }
1266-
impl_additive! { f64, 0.0 }
1293+
impl_additive! { f32, 0.0 }
1294+
impl_additive! { f64, 0.0 }
12671295

12681296
/// A trait for iterators over elements which can be multiplied together.
12691297
#[unstable(feature = "core",
12701298
reason = "needs to be re-evaluated as part of numerics reform")]
1271-
pub trait MultiplicativeIterator<A> {
1299+
pub trait MultiplicativeIterator {
1300+
/// The result of multiplying the elements of the iterator.
1301+
type ProductResult;
1302+
12721303
/// Iterates over the entire iterator, multiplying all the elements
12731304
///
12741305
/// # Examples
@@ -1284,29 +1315,54 @@ pub trait MultiplicativeIterator<A> {
12841315
/// assert!(factorial(1) == 1);
12851316
/// assert!(factorial(5) == 120);
12861317
/// ```
1287-
fn product(self) -> A;
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;
12881331
}
12891332

1290-
macro_rules! impl_multiplicative {
1291-
($A:ty, $init:expr) => {
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) => {
12921349
#[unstable(feature = "core", reason = "trait is experimental")]
1293-
impl<T: Iterator<Item=$A>> MultiplicativeIterator<$A> for T {
1294-
#[inline]
1295-
fn product(self) -> $A {
1296-
self.fold($init, |acc, x| acc * x)
1297-
}
1350+
impl MultiplicativeIteratorItem for $T {
1351+
type ProductResult = $T;
1352+
fn start() -> $T { $init }
1353+
fn combine(self, other: $T) -> $T { self * other }
12981354
}
12991355
};
13001356
}
1301-
impl_multiplicative! { i8, 1 }
1302-
impl_multiplicative! { i16, 1 }
1303-
impl_multiplicative! { i32, 1 }
1304-
impl_multiplicative! { i64, 1 }
1305-
impl_multiplicative! { isize, 1 }
1306-
impl_multiplicative! { u8, 1 }
1307-
impl_multiplicative! { u16, 1 }
1308-
impl_multiplicative! { u32, 1 }
1309-
impl_multiplicative! { u64, 1 }
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 }
13101366
impl_multiplicative! { usize, 1 }
13111367
impl_multiplicative! { f32, 1.0 }
13121368
impl_multiplicative! { f64, 1.0 }

0 commit comments

Comments
 (0)