diff --git a/Cargo.toml b/Cargo.toml index d6dc3fa24..7fb6a3980 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,7 +57,7 @@ name = "combinations_with_replacement" harness = false [[bench]] -name = "tree_fold1" +name = "tree_reduce" harness = false [[bench]] diff --git a/benches/tree_fold1.rs b/benches/tree_reduce.rs similarity index 86% rename from benches/tree_fold1.rs rename to benches/tree_reduce.rs index 5b76d5404..051b14883 100644 --- a/benches/tree_fold1.rs +++ b/benches/tree_reduce.rs @@ -6,7 +6,7 @@ use itertools::{cloned, Itertools}; trait IterEx: Iterator { // Another efficient implementation against which to compare, // but needs `std` so is less desirable. - fn tree_fold1_vec(self, mut f: F) -> Option + fn tree_reduce_vec(self, mut f: F) -> Option where F: FnMut(Self::Item, Self::Item) -> Self::Item, Self: Sized, @@ -91,14 +91,14 @@ def_benchs! { def_benchs! { 10_000, - tree_fold1, - tree_fold1_stack_10k, + tree_reduce, + tree_reduce_stack_10k, } def_benchs! { 10_000, - tree_fold1_vec, - tree_fold1_vec_10k, + tree_reduce_vec, + tree_reduce_vec_10k, } def_benchs! { @@ -109,14 +109,14 @@ def_benchs! { def_benchs! { 100, - tree_fold1, - tree_fold1_stack_100, + tree_reduce, + tree_reduce_stack_100, } def_benchs! { 100, - tree_fold1_vec, - tree_fold1_vec_100, + tree_reduce_vec, + tree_reduce_vec_100, } def_benchs! { @@ -127,24 +127,24 @@ def_benchs! { def_benchs! { 8, - tree_fold1, - tree_fold1_stack_08, + tree_reduce, + tree_reduce_stack_08, } def_benchs! { 8, - tree_fold1_vec, - tree_fold1_vec_08, + tree_reduce_vec, + tree_reduce_vec_08, } criterion_main!( fold1_10k, - tree_fold1_stack_10k, - tree_fold1_vec_10k, + tree_reduce_stack_10k, + tree_reduce_vec_10k, fold1_100, - tree_fold1_stack_100, - tree_fold1_vec_100, + tree_reduce_stack_100, + tree_reduce_vec_100, fold1_08, - tree_fold1_stack_08, - tree_fold1_vec_08, + tree_reduce_stack_08, + tree_reduce_vec_08, ); diff --git a/src/lib.rs b/src/lib.rs index 0506a3d84..0325c6d01 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2466,7 +2466,7 @@ pub trait Itertools: Iterator { /// - if `f` is a trivial operation like `u32::wrapping_add`, prefer the normal /// [`Iterator::reduce`] instead since it will most likely result in the generation of simpler /// code because the compiler is able to optimize it - /// - otherwise if `f` is non-trivial like `format!`, you should use `tree_fold1` since it + /// - otherwise if `f` is non-trivial like `format!`, you should use `tree_reduce` since it /// reduces the number of operations from `O(n)` to `O(ln(n))` /// /// Here "non-trivial" means: @@ -2479,20 +2479,20 @@ pub trait Itertools: Iterator { /// /// // The same tree as above /// let num_strings = (1..8).map(|x| x.to_string()); - /// assert_eq!(num_strings.tree_fold1(|x, y| format!("f({}, {})", x, y)), + /// assert_eq!(num_strings.tree_reduce(|x, y| format!("f({}, {})", x, y)), /// Some(String::from("f(f(f(1, 2), f(3, 4)), f(f(5, 6), 7))"))); /// /// // Like fold1, an empty iterator produces None - /// assert_eq!((0..0).tree_fold1(|x, y| x * y), None); + /// assert_eq!((0..0).tree_reduce(|x, y| x * y), None); /// - /// // tree_fold1 matches fold1 for associative operations... - /// assert_eq!((0..10).tree_fold1(|x, y| x + y), + /// // tree_reduce matches fold1 for associative operations... + /// assert_eq!((0..10).tree_reduce(|x, y| x + y), /// (0..10).fold1(|x, y| x + y)); /// // ...but not for non-associative ones - /// assert_ne!((0..10).tree_fold1(|x, y| x - y), + /// assert_ne!((0..10).tree_reduce(|x, y| x - y), /// (0..10).fold1(|x, y| x - y)); /// ``` - fn tree_fold1(mut self, mut f: F) -> Option + fn tree_reduce(mut self, mut f: F) -> Option where F: FnMut(Self::Item, Self::Item) -> Self::Item, Self: Sized, @@ -2505,7 +2505,7 @@ pub trait Itertools: Iterator { FF: FnMut(T, T) -> T, { // This function could be replaced with `it.next().ok_or(None)`, - // but half the useful tree_fold1 work is combining adjacent items, + // but half the useful tree_reduce work is combining adjacent items, // so put that in a form that LLVM is more likely to optimize well. let a = if let Some(v) = it.next() { @@ -2555,6 +2555,16 @@ pub trait Itertools: Iterator { } } + /// See [`.tree_reduce()`](Itertools::tree_reduce). + #[deprecated(note = "Use .tree_reduce() instead", since = "0.13.0")] + fn tree_fold1(self, f: F) -> Option + where + F: FnMut(Self::Item, Self::Item) -> Self::Item, + Self: Sized, + { + self.tree_reduce(f) + } + /// An iterator method that applies a function, producing a single, final value. /// /// `fold_while()` is basically equivalent to [`Iterator::fold`] but with additional support for diff --git a/tests/quick.rs b/tests/quick.rs index 7b163d8dc..217ccbdc2 100644 --- a/tests/quick.rs +++ b/tests/quick.rs @@ -1334,7 +1334,7 @@ quickcheck! { } quickcheck! { - fn tree_fold1_f64(mut a: Vec) -> TestResult { + fn tree_reduce_f64(mut a: Vec) -> TestResult { fn collapse_adjacent(x: Vec, mut f: F) -> Vec where F: FnMut(f64, f64) -> f64 { @@ -1353,7 +1353,7 @@ quickcheck! { return TestResult::discard(); } - let actual = a.iter().cloned().tree_fold1(f64::atan2); + let actual = a.iter().cloned().tree_reduce(f64::atan2); while a.len() > 1 { a = collapse_adjacent(a, f64::atan2); diff --git a/tests/test_core.rs b/tests/test_core.rs index 448f39652..b5826ef39 100644 --- a/tests/test_core.rs +++ b/tests/test_core.rs @@ -278,9 +278,9 @@ fn part() { } #[test] -fn tree_fold1() { +fn tree_reduce() { for i in 0..100 { - assert_eq!((0..i).tree_fold1(|x, y| x + y), (0..i).fold1(|x, y| x + y)); + assert_eq!((0..i).tree_reduce(|x, y| x + y), (0..i).fold1(|x, y| x + y)); } } diff --git a/tests/test_std.rs b/tests/test_std.rs index 50110533d..1f319d8d3 100644 --- a/tests/test_std.rs +++ b/tests/test_std.rs @@ -1434,7 +1434,7 @@ fn fold_while() { } #[test] -fn tree_fold1() { +fn tree_reduce() { let x = [ "", "0", @@ -1461,7 +1461,7 @@ fn tree_fold1() { Some(s.to_string()) }; let num_strings = (0..i).map(|x| x.to_string()); - let actual = num_strings.tree_fold1(|a, b| format!("{} {} x", a, b)); + let actual = num_strings.tree_reduce(|a, b| format!("{} {} x", a, b)); assert_eq!(actual, expected); } }