Collections .filter() and error handling

What is the idiomatic way to do error handling when using collection.filter(|e| {...})

Say for example when doing something like:

let filtered = read_dir(path).filter(|e| {
   e.unwrap().is_dir()
});

I want to avoid the unwrap and actually bubble up the error if there is one. My use case also goes into the fallible OsStr -> UTF-8 check conversion which I also want to "catch" properly and not just do something silly like unwrap() or use unwrap_or("")

Given that filter closure expects bool result, how can I "bubble" up the errors that can occur inside it?

One option would be to filter in a way that preserves errors, and then collapse the errors down to the first one. You can do this lazily so that execution stops at the first error. For example,

let dirs: Result<Vec<_>> = read_dir(path)
    .filter(|e| e.as_ref().map(|f| f.is_dir()).unwrap_or(true))
    .collect();

This exploits the fact that collect on an iterator of Result produces a Result of some collection (here, vec, but could be another).

1 Like