The two functions below do the same thing. But the for version is significantly faster than the fold version.
I know this isn't a proper benchmark but I ran this program multiple times and the difference was always significant, especially if you make the value of limit larger.
I ran the code in the playground using stable, beta and nightly (all using release) and the results are the same.
I think it has to do with recursion since my other mini programs containing fold and recursion show the same slower performance compared to their for counterparts. Those that don't have recursion don't show such behavior.
fn count_of_50_smooths_for(limit: u64, cur_smooth: u64, primes: &[u64]) -> u64 {
let mut acc = 0;
for (i, &p) in primes.iter().enumerate().take_while(|(_, &p)| p <= limit / cur_smooth) {
acc += 1 + count_of_50_smooths_for(limit, cur_smooth * p, &primes[i..]);
}
acc
}
fn count_of_50_smooths_fold(limit: u64, cur_smooth: u64, primes: &[u64]) -> u64 {
primes.iter().enumerate().take_while(|(_, &p)| p <= limit / cur_smooth).fold(0, |acc, (i, &p)| {
acc + 1 + count_of_50_smooths_fold(limit, cur_smooth * p, &primes[i..])
})
}
fn main() {
let timer = std::time::Instant::now();
println!("using for loop:");
println!(" result: {}", count_of_50_smooths_for(2u64.pow(50), 1, &[2, 3, 5, 7, 11, 13, 17, 19, 23, 27, 31, 37, 41, 43, 47]));//, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]));
println!(" time: {:?}", timer.elapsed());
let timer = std::time::Instant::now();
println!("using fold:");
println!(" result: {}", count_of_50_smooths_fold(2u64.pow(50), 1, &[2, 3, 5, 7, 11, 13, 17, 19, 23, 27, 31, 37, 41, 43, 47]));//, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]));
println!(" time: {:?}", timer.elapsed());
}