What's the idiomatic functional way to return a Result from a iter::map()?

Consider the following simple program:

fn main() {
    let v = vec![1,2,4,5,6];
    let result: Vec<i32> = v.into_iter().map(|e| {
        if e < 4 {
            return e;
        } else {
            // return some error using Result<>?
            return -1;
        }
    }).collect();
    println!("{:?}", result);
}

I would like to have result to have this return type: Result<Vec<i32>, Box<dyn std::error::Error>>, where instead of returning -1, it'd be some error.

I can do this with looping and similar, but I don't want to loop. I'd like to practice more functional programming for security applications.

Is this doable?

You can collect directly to Result-wrapped collections, which will halt on Err:

fn main() {
    let v = vec![1,2,4,5,6];
    let result: Result<Vec<i32>, i32> = v.into_iter().map(|e| {
        if e < 4 {
            Ok(e)
        } else {
            Err(-1) // or whatever error type
        }
    }).collect();
    println!("{:?}", result);
}
1 Like

Thanks, but I'm confused. How can evaluating one iteration through a closure, which is supposed to return one element in the vector, return a full result of the whole mapping?

This is handled by impl<A, E, V> FromIterator<Result<A, E>> for Result<V, E>.

Given an iterator of Result<A, E> items, each Ok(A) is forwarded to the collection's FromIterator<A> for V, and at the end it will return that Ok(V). But if the iterator produces any Err(E), it will stop right away and return that error directly.

1 Like

Very, very interesting. Thank you very much for explaining!