Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is try_fold the preferred way to stop an infinite iteration or are there more idiomatic alternatives?

Tags:

iteration

rust

I'm looking for ways to interrupt iteration of an infinite iterator. I found that try_fold accomplishes my objective. However, that requires doing the awkward thing of returning an Err on the successful case. What I'm looking to understand is if this is an idiomatic way of doing things. The only other way I can think of doing this is using a regular for, or something like a find while keeping external state (which feels even weirder!). I know in clojure there's reduced, but I couldn't find an equivalent for rust.

Here's a minimum viable example. The example cycles around the initial Vec, summing each item as it goes, and stops at the first sum larger than 10. I.e. it returns 12, because 1 + 5 - 3 + 1 + 5 - 3 + 1 + 5 = 12:

fn main() {
    let seed = vec![1, 5, -3];

    let res = seed.iter().cycle().try_fold(0, |accum, value| {
        let next = accum + value;
        if next > 10 {
            Err(next)
        } else {
            Ok(next)
        }
    });
    if let Err(res) = res {
        println!("{:?}", res);
    } else {
        unreachable!();
    }
}

(playground link)

The part that feels weird to me is the if let Err(res) = res being the positive condition and really the only way out of the cycle (hence why the other branch is unreachable).

Is there a 'better' way?

like image 306
jgpaiva Avatar asked Dec 13 '22 07:12

jgpaiva


1 Answers

Simple, just iterate normally

fn main() {
    let seed = vec![1, 5, -3];
    let mut accum = 0;
    for value in seed.iter().cycle() {
        accum += value;
        if accum > 10 {
            break;
        }
    }
    println!("{:?}", accum)
}
like image 161
Krish Avatar answered Jun 21 '23 05:06

Krish