问题
I would like the iterator to be filtered, but my predicate has the possibility of failing. When the predicate fails, I'd like to fail the entire function. In this example, I'd like work
to return the Result
generated by maybe
:
fn maybe(v: u32) -> Result<bool, u8> {
match v % 3 {
0 => Ok(true),
1 => Ok(false),
2 => Err(42),
}
}
fn work() -> Result<Vec<u32>, u8> {
[1, 2, 3, 4, 5].iter().filter(|&&x| maybe(x)).collect()
}
fn main() {
println!("{:?}", work())
}
error[E0308]: mismatched types
--> src/main.rs:10:45
|
10 | [1, 2, 3, 4, 5].iter().filter(|&&x| maybe(x)).collect()
| ^^^^^^^^ expected bool, found enum `std::result::Result`
|
= note: expected type `bool`
found type `std::result::Result<bool, u8>`
error[E0277]: the trait bound `std::result::Result<std::vec::Vec<u32>, u8>: std::iter::FromIterator<&u32>` is not satisfied
--> src/main.rs:10:55
|
10 | [1, 2, 3, 4, 5].iter().filter(|&&x| maybe(x)).collect()
| ^^^^^^^ a collection of type `std::result::Result<std::vec::Vec<u32>, u8>` cannot be built from an iterator over elements of type `&u32`
|
= help: the trait `std::iter::FromIterator<&u32>` is not implemented for `std::result::Result<std::vec::Vec<u32>, u8>`
回答1:
You can turn the Result<bool, u8>
into an Option<Result<u32, u8>>
, that is, pull the bool
out to an Option
and put the value inside, and use filter_map
:
fn maybe(v: u32) -> Result<bool, u8> {
match v % 3 {
0 => Ok(true),
1 => Ok(false),
_ => Err(42),
}
}
fn work() -> Result<Vec<u32>, u8> {
[1, 2, 3, 4, 5]
.iter()
.filter_map(|&x| match maybe(x) {
Ok(true) => Some(Ok(x)),
Ok(false) => None,
Err(e) => Some(Err(e)),
})
.collect()
}
fn main() {
println!("{:?}", work())
}
playground
来源:https://stackoverflow.com/questions/28036173/how-can-i-filter-an-iterator-when-the-predicate-returns-a-resultbool