Как остановить итерацию и вернуть ошибку, когда Iterator:: map возвращает результат: Err?
У меня есть функция, которая возвращает Result
:
fn find(id: &Id) -> Result<Item, ItemError> {
// ...
}
Затем другой, используя его следующим образом:
let parent_items: Vec<Item> = parent_ids.iter()
.map(|id| find(id).unwrap())
.collect();
Как мне обрабатывать случай сбоя внутри любой из map
итераций?
Я знаю, что могу использовать flat_map
, и в этом случае ошибки будут проигнорированы:
let parent_items: Vec<Item> = parent_ids.iter()
.flat_map(|id| find(id).into_iter())
.collect();
Result
Итератор имеет либо 0, либо 1 элемент в зависимости от состояния успеха, а flat_map
будет отфильтровывать его, если он равен 0.
Однако я не хочу игнорировать ошибки, вместо этого хочу, чтобы весь блок кода просто остановился и возвратил новую ошибку (на основе ошибки, возникшей на карте или просто пересылающей существующую ошибку).
Как лучше всего справиться с этим в Rust?
Ответы
Ответ 1
Result
реализует FromIterator
, поэтому вы можете перемещать Result
снаружи, и итераторы позаботятся об остальном (включая остановку итерации, если ошибка найдено).
#[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);
}
Игровая площадка
Ответ 2
Этот ответ относится к версии ржавчины до версии 1.0, и необходимые функции были удалены
Вы можете использовать std::result::fold
для этого. Он останавливает повторение после первого Err
.
Пример программы, которую я только что написал:
fn main() {
println!("{}", go([1, 2, 3]));
println!("{}", go([1, -2, 3]));
}
fn go(v: &[int]) -> Result<Vec<int>, String> {
std::result::fold(
v.iter().map(|&n| is_positive(n)),
vec![],
|mut v, e| {
v.push(e);
v
})
}
fn is_positive(n: int) -> Result<int, String> {
if n > 0 {
Ok(n)
} else {
Err(format!("{} is not positive!", n))
}
}
Вывод:
Ok([1, 2, 3])
Err(-2 is not positive!)
Демо