Suppose I have a collection of Result
items, like:
let items: &[Result<&str, u32>] = &[Ok("foo"), Err(444), Ok("bar")];
I need to find the index of the first element with the value "bar"
. My first attempt looks like:
let bar_idx = items.iter()
.position(|item| item? == "bar")?;
This won't work because of the ?
operator inside the closure.
I'm aware of the try_for_each
method, which fails the entire collection if an Err
is returned, but there is no such equivalent for position
, which is what I'm trying to do.
How can I implement this search?
EDIT:
I opened an issue at Rust repo, because I believe try_position
should exist.
You can build one on top of try_for_each()
:
use std::ops::ControlFlow;
let item: ControlFlow<Result<usize, u32>> =
items
.iter()
.enumerate()
.try_for_each(|(idx, item)| match item {
Ok(v) if *v == "bar" => ControlFlow::Break(Ok(idx)),
Ok(_) => ControlFlow::Continue(()),
Err(err) => ControlFlow::Break(Err(*err)),
});
// Can replace by `ControlFlow::break_value()` once stabilized.
let item = match item {
ControlFlow::Break(v) => Some(v),
ControlFlow::Continue(()) => None,
};
But frankly, it's likely better to use a simple for
loop:
let mut result = None;
for (idx, item) in items.iter().enumerate() {
match item {
Ok(v) if *v == "bar" => {
result = Some(Ok(idx));
break;
}
Ok(_) => {}
Err(err) => {
result = Some(Err(*err));
break;
}
}
}