Breaking out of a (fold) iterator?

So a pretty standard pattern in imperative programming is to create some mutable state (like sum), then iterate over some values, check a predicate, and if the predicate fails, break the for-loop.

the functional tool, fold does something similar, but I can't break out of the iterator. I can instead use something like take_while, but that's the best I can think of.

Is that my best shot here?

fn main() {
    // some vector of maybe bad overflow stuff
    let p: Vec<u128> = vec![0, 1, 2, 3, 4];
    let mut is_overflow = false;
    let sum: u128 = p.iter().fold(0, |acc, &amt| {
        match u128::checked_add(acc, amt) {
            None => {
                is_overflow = true;
                0
                //break; // can't!
            }
            Some(x) => x,
        }
    });
    dbg!(sum);

    let mut sum = 0;
    let mut is_overflow = false;
    let _: Vec<_> = p
        .into_iter()
        .take_while(|&amt| match u128::checked_add(sum, amt) {
            Some(x) => {
                sum = x;
                true
            }
            None => {
                is_overflow = true;
                false
            }
        })
        .collect();
    dbg!(sum);
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=4a81b5a9849ce3a5401446e873369e0f

There is try_fold, which lets you return Ok to continue and Err to break out of it.

https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.try_fold

I'm on my phone now so it's hard to type an example

1 Like

That's dedication to the Rust community. Thanks!

my example is literally in the doc comment. LOL

/// // This sum overflows when adding the 100 element
    /// let sum = it.try_fold(0i8, |acc, &x| acc.checked_add(x));
    /// assert_eq!(sum, None);
    ```
3 Likes

Another flavor of a sum using a subset of the values is to use filter. Clearly different than a “break when”, but often used.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.