Auto merge of #23293 - tbu-:pr_additive_multiplicative, r=alexcrichton

Previously it could not be implemented for types outside `libcore/iter.rs` due
to coherence issues.
This commit is contained in:
bors 2015-04-08 00:42:10 +00:00
commit dd6c4a8f15
16 changed files with 89 additions and 133 deletions

View File

@ -85,7 +85,6 @@ use core::clone::Clone;
use core::cmp::Ordering::{self, Greater, Less};
use core::cmp::{self, Ord, PartialEq};
use core::iter::Iterator;
use core::iter::MultiplicativeIterator;
use core::marker::Sized;
use core::mem::size_of;
use core::mem;
@ -1182,7 +1181,7 @@ impl Iterator for ElementSwaps {
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
// For a vector of size n, there are exactly n! permutations.
let n = (2..self.sdir.len() + 1).product();
let n: usize = (2..self.sdir.len() + 1).product();
(n - self.swaps_made, Some(n - self.swaps_made))
}
}

View File

@ -53,7 +53,6 @@ use self::RecompositionState::*;
use self::DecompositionType::*;
use core::clone::Clone;
use core::iter::AdditiveIterator;
use core::iter::{Iterator, Extend};
use core::option::Option::{self, Some, None};
use core::result::Result;
@ -116,7 +115,7 @@ impl<S: AsRef<str>> SliceConcatExt<str, String> for [S] {
// this is wrong without the guarantee that `self` is non-empty
// `len` calculation may overflow but push_str but will check boundaries
let len = sep.len() * (self.len() - 1)
+ self.iter().map(|s| s.as_ref().len()).sum();
+ self.iter().map(|s| s.as_ref().len()).sum::<usize>();
let mut result = String::with_capacity(len);
let mut first = true;

View File

@ -9,7 +9,6 @@
// except according to those terms.
use std::cmp::Ordering::{Equal, Greater, Less};
use std::iter::AdditiveIterator;
use std::str::{Utf8Error, from_utf8};
#[test]

View File

@ -65,7 +65,7 @@ use default::Default;
use marker;
use mem;
use num::{Int, Zero, One};
use ops::{self, Add, Sub, FnMut, RangeFrom};
use ops::{self, Add, Sub, FnMut, Mul, RangeFrom};
use option::Option::{self, Some, None};
use marker::Sized;
use usize;
@ -489,15 +489,14 @@ pub trait Iterator {
///
/// ```
/// # #![feature(core)]
/// use std::iter::AdditiveIterator;
///
/// let a = [1, 4, 2, 3, 8, 9, 6];
/// let sum = a.iter()
/// .map(|x| *x)
/// .inspect(|&x| println!("filtering {}", x))
/// .filter(|&x| x % 2 == 0)
/// .inspect(|&x| println!("{} made it through", x))
/// .sum();
/// let sum: i32 = a.iter()
/// .map(|x| *x)
/// .inspect(|&x| println!("filtering {}", x))
/// .filter(|&x| x % 2 == 0)
/// .inspect(|&x| println!("{} made it through", x))
/// .sum();
/// println!("{}", sum);
/// ```
#[inline]
@ -1022,6 +1021,47 @@ pub trait Iterator {
}
}
}
/// Iterates over the entire iterator, summing up all the elements
///
/// # Examples
///
/// ```
/// # #![feature(core)]
///
/// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter().cloned();
/// assert!(it.sum::<i32>() == 15);
/// ```
#[unstable(feature="core")]
fn sum<S=<Self as Iterator>::Item>(self) -> S where
S: Add<Self::Item, Output=S> + Zero,
Self: Sized,
{
self.fold(Zero::zero(), |s, e| s + e)
}
/// Iterates over the entire iterator, multiplying all the elements
///
/// # Examples
///
/// ```
/// # #![feature(core)]
///
/// fn factorial(n: u32) -> u32 {
/// (1..).take_while(|&i| i <= n).product()
/// }
/// assert!(factorial(0) == 1);
/// assert!(factorial(1) == 1);
/// assert!(factorial(5) == 120);
/// ```
#[unstable(feature="core")]
fn product<P=<Self as Iterator>::Item>(self) -> P where
P: Mul<Self::Item, Output=P> + One,
Self: Sized,
{
self.fold(One::one(), |p, e| p * e)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
@ -1222,95 +1262,6 @@ impl<I> RandomAccessIterator for Rev<I>
}
}
/// A trait for iterators over elements which can be added together
#[unstable(feature = "core",
reason = "needs to be re-evaluated as part of numerics reform")]
pub trait AdditiveIterator<A> {
/// Iterates over the entire iterator, summing up all the elements
///
/// # Examples
///
/// ```
/// # #![feature(core)]
/// use std::iter::AdditiveIterator;
///
/// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter().cloned();
/// assert!(it.sum() == 15);
/// ```
fn sum(self) -> A;
}
macro_rules! impl_additive {
($A:ty, $init:expr) => {
#[unstable(feature = "core", reason = "trait is experimental")]
impl<T: Iterator<Item=$A>> AdditiveIterator<$A> for T {
#[inline]
fn sum(self) -> $A {
self.fold($init, |acc, x| acc + x)
}
}
};
}
impl_additive! { i8, 0 }
impl_additive! { i16, 0 }
impl_additive! { i32, 0 }
impl_additive! { i64, 0 }
impl_additive! { isize, 0 }
impl_additive! { u8, 0 }
impl_additive! { u16, 0 }
impl_additive! { u32, 0 }
impl_additive! { u64, 0 }
impl_additive! { usize, 0 }
impl_additive! { f32, 0.0 }
impl_additive! { f64, 0.0 }
/// A trait for iterators over elements which can be multiplied together.
#[unstable(feature = "core",
reason = "needs to be re-evaluated as part of numerics reform")]
pub trait MultiplicativeIterator<A> {
/// Iterates over the entire iterator, multiplying all the elements
///
/// # Examples
///
/// ```
/// # #![feature(core)]
/// use std::iter::MultiplicativeIterator;
///
/// fn factorial(n: usize) -> usize {
/// (1..).take_while(|&i| i <= n).product()
/// }
/// assert!(factorial(0) == 1);
/// assert!(factorial(1) == 1);
/// assert!(factorial(5) == 120);
/// ```
fn product(self) -> A;
}
macro_rules! impl_multiplicative {
($A:ty, $init:expr) => {
#[unstable(feature = "core", reason = "trait is experimental")]
impl<T: Iterator<Item=$A>> MultiplicativeIterator<$A> for T {
#[inline]
fn product(self) -> $A {
self.fold($init, |acc, x| acc * x)
}
}
};
}
impl_multiplicative! { i8, 1 }
impl_multiplicative! { i16, 1 }
impl_multiplicative! { i32, 1 }
impl_multiplicative! { i64, 1 }
impl_multiplicative! { isize, 1 }
impl_multiplicative! { u8, 1 }
impl_multiplicative! { u16, 1 }
impl_multiplicative! { u32, 1 }
impl_multiplicative! { u64, 1 }
impl_multiplicative! { usize, 1 }
impl_multiplicative! { f32, 1.0 }
impl_multiplicative! { f64, 1.0 }
/// `MinMaxResult` is an enum returned by `min_max`. See `Iterator::min_max` for
/// more detail.
#[derive(Clone, PartialEq, Debug)]

View File

@ -86,6 +86,20 @@ macro_rules! zero_one_impl {
}
zero_one_impl! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
macro_rules! zero_one_impl_float {
($($t:ty)*) => ($(
impl Zero for $t {
#[inline]
fn zero() -> $t { 0.0 }
}
impl One for $t {
#[inline]
fn one() -> $t { 1.0 }
}
)*)
}
zero_one_impl_float! { f32 f64 }
/// A built-in signed or unsigned integer.
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0",

View File

@ -329,17 +329,17 @@ fn test_iterator_len() {
#[test]
fn test_iterator_sum() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
assert_eq!(v[..4].iter().cloned().sum(), 6);
assert_eq!(v.iter().cloned().sum(), 55);
assert_eq!(v[..0].iter().cloned().sum(), 0);
assert_eq!(v[..4].iter().cloned().sum::<i32>(), 6);
assert_eq!(v.iter().cloned().sum::<i32>(), 55);
assert_eq!(v[..0].iter().cloned().sum::<i32>(), 0);
}
#[test]
fn test_iterator_product() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
assert_eq!(v[..4].iter().cloned().product(), 0);
assert_eq!(v[1..5].iter().cloned().product(), 24);
assert_eq!(v[..0].iter().cloned().product(), 1);
assert_eq!(v[..4].iter().cloned().product::<i32>(), 0);
assert_eq!(v[1..5].iter().cloned().product::<i32>(), 24);
assert_eq!(v[..0].iter().cloned().product::<i32>(), 1);
}
#[test]

View File

@ -26,7 +26,7 @@ use middle::ty::*;
use middle::ty;
use std::cmp::Ordering;
use std::fmt;
use std::iter::{range_inclusive, AdditiveIterator, FromIterator, IntoIterator, repeat};
use std::iter::{range_inclusive, FromIterator, IntoIterator, repeat};
use std::slice;
use syntax::ast::{self, DUMMY_NODE_ID, NodeId, Pat};
use syntax::ast_util;
@ -76,7 +76,7 @@ impl<'a> fmt::Debug for Matrix<'a> {
pretty_printed_matrix.iter().map(|row| row[col].len()).max().unwrap_or(0)
}).collect();
let total_width = column_widths.iter().cloned().sum() + column_count * 3 + 1;
let total_width = column_widths.iter().cloned().sum::<usize>() + column_count * 3 + 1;
let br = repeat('+').take(total_width).collect::<String>();
try!(write!(f, "{}\n", br));
for row in pretty_printed_matrix {

View File

@ -220,7 +220,6 @@ use util::ppaux::{Repr, vec_map_to_string};
use std;
use std::cmp::Ordering;
use std::iter::AdditiveIterator;
use std::rc::Rc;
use syntax::ast;
use syntax::ast::{DUMMY_NODE_ID, NodeId};

View File

@ -61,7 +61,7 @@ use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
use util::common::{ErrorReported, FN_OUTPUT_NAME};
use util::ppaux::{self, Repr, UserString};
use std::iter::{repeat, AdditiveIterator};
use std::iter::repeat;
use std::rc::Rc;
use std::slice;
use syntax::{abi, ast, ast_util};
@ -517,12 +517,13 @@ fn find_implied_output_region(input_tys: &[Ty], input_pats: Vec<String>)
lifetimes_for_params.push((input_pat, accumulator.len()));
}
let implied_output_region = if lifetimes_for_params.iter().map(|&(_, n)| n).sum() == 1 {
assert!(possible_implied_output_region.is_some());
possible_implied_output_region
} else {
None
};
let implied_output_region =
if lifetimes_for_params.iter().map(|&(_, n)| n).sum::<usize>() == 1 {
assert!(possible_implied_output_region.is_some());
possible_implied_output_region
} else {
None
};
(implied_output_region, lifetimes_for_params)
}

View File

@ -15,8 +15,7 @@ use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd};
use fmt;
use hash;
use old_io::Writer;
use iter::{AdditiveIterator, Extend};
use iter::{Iterator, Map};
use iter::{Extend, Iterator, Map};
use marker::Sized;
use option::Option::{self, Some, None};
use result::Result::{self, Ok, Err};
@ -351,7 +350,7 @@ impl Path {
Some(vec![SEP_BYTE])
} else {
let n = if is_abs { comps.len() } else { comps.len() - 1} +
comps.iter().map(|v| v.len()).sum();
comps.iter().map(|v| v.len()).sum::<usize>();
let mut v = Vec::with_capacity(n);
let mut it = comps.into_iter();
if !is_abs {

View File

@ -20,8 +20,7 @@ use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd};
use fmt;
use hash;
use old_io::Writer;
use iter::{AdditiveIterator, Extend};
use iter::{Iterator, Map, repeat};
use iter::{Extend, Iterator, Map, repeat};
use mem;
use option::Option::{self, Some, None};
use result::Result::{self, Ok, Err};
@ -785,7 +784,7 @@ impl Path {
let prefix_ = &s[..prefix_len(prefix)];
let n = prefix_.len() +
if is_abs { comps.len() } else { comps.len() - 1} +
comps.iter().map(|v| v.len()).sum();
comps.iter().map(|v| v.len()).sum::<usize>();
let mut s = String::with_capacity(n);
match prefix {
Some(DiskPrefix) => {

View File

@ -20,7 +20,7 @@ use core::prelude::*;
use core::char;
use core::cmp;
use core::iter::{Filter, AdditiveIterator};
use core::iter::Filter;
use core::mem;
use core::slice;
use core::str::Split;

View File

@ -13,7 +13,6 @@
use std::io::prelude::*;
use std::io::BufReader;
use std::iter;
use std::iter::AdditiveIterator;
use std::path::{Path, PathBuf};
pub struct BookItem {
@ -151,7 +150,7 @@ pub fn parse_summary(input: &mut Read, src: &Path) -> Result<Book, Vec<String>>
'\t' => 4,
_ => unreachable!()
}
}).sum() / 4 + 1;
}).sum::<usize>() / 4 + 1;
if level > stack.len() + 1 {
errors.push(format!("section '{}' is indented too deeply; \

View File

@ -43,7 +43,7 @@
#![allow(non_snake_case)]
#![feature(unboxed_closures, core, os)]
use std::iter::{repeat, AdditiveIterator};
use std::iter::repeat;
use std::thread;
use std::mem;
use std::num::Float;

View File

@ -12,8 +12,7 @@
#![feature(core)]
use std::iter::AdditiveIterator;
fn main() {
let x: [u64; 3] = [1, 2, 3];
assert_eq!(6, (0..3).map(|i| x[i]).sum());
assert_eq!(6, (0..3).map(|i| x[i]).sum::<u64>());
}

View File

@ -15,10 +15,8 @@
#![feature(core)]
use std::iter::AdditiveIterator;
fn square_sum(v: &[i64]) -> i64 {
let sum = v.iter().cloned().sum();
let sum: i64 = v.iter().cloned().sum();
sum * sum
}