HiveBrain v1.2.0
Get Started
← Back to all entries
debugrustCritical

How do I stop iteration and return an error when Iterator::map returns a Result::Err?

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
errorhowiterationreturnerrreturnsanditeratorstopresult

Problem

I have a function that returns a Result:

fn find(id: &Id) -> Result {
    // ...
}


Then another using it like this:

let parent_items: Vec = parent_ids.iter()
    .map(|id| find(id).unwrap())
    .collect();


How do I handle the case of failure inside any of the map iterations?

I know I could use flat_map and in this case the error results would be ignored:

let parent_items: Vec = parent_ids.iter()
    .flat_map(|id| find(id).into_iter())
    .collect();


Result's iterator has either 0 or 1 items depending on the success state, and flat_map will filter it out if it's 0.

However, I don't want to ignore errors, I want to instead make the whole code block just stop and return a new error (based on the error that came up within the map, or just forward the existing error).

How do I best handle this in Rust?

Solution

Result implements FromIterator, so you can move the Result outside and iterators will take care of the rest (including stopping iteration if an error is found).

#[derive(Debug)]
struct Item;
type Id = String;

fn find(id: &Id) -> Result {
    Err(format!("Not found: {:?}", id))
}

fn main() {
    let s = |s: &str| s.to_string();
    let ids = vec![s("1"), s("2"), s("3")];

    let items: Result, _> = ids.iter().map(find).collect();
    println!("Result: {:?}", items);
}


Playground

Code Snippets

#[derive(Debug)]
struct Item;
type Id = String;

fn find(id: &Id) -> Result<Item, String> {
    Err(format!("Not found: {:?}", id))
}

fn main() {
    let s = |s: &str| s.to_string();
    let ids = vec![s("1"), s("2"), s("3")];

    let items: Result<Vec<_>, _> = ids.iter().map(find).collect();
    println!("Result: {:?}", items);
}

Context

Stack Overflow Q#26368288, score: 328

Revisions (0)

No revisions yet.