Option
有ok_or
将Some
映射到Ok
和None
映射到Err
,例如:< / p>
let foo = iterator.next().ok_or(MyError)?;
如果我想在已经采取必要的项目(预期数量)后验证迭代器返回None
,我应该使用什么?如果Ok
我正在寻找返回None
的内容,而其他情况下会返回自定义错误:
let _ = iterator.next().the_method_i_search(|elem| MyError::MyCase(elem))?;
我知道我能做到:
if let Some(elem) = iterator.next() {
return Err(MyError::MyCase(elem));
}
但我喜欢Rust中?
运算符和方法链的简洁性。
答案 0 :(得分:4)
我将假设最初的问题是从迭代器中获取N个元素,并在迭代器之后仍然有更多元素时引发错误。我首先通过创建一个新的迭代器适配器TakeExactly
来解决这个问题,它产生一个Result
的迭代器。在第一次n
检索之后,迭代器将开始将项目作为错误返回。
use std::iter::Iterator;
struct TakeExactly<I> {
it: I,
n: usize,
}
impl<I> Iterator for TakeExactly<I>
where
I: Iterator
{
type Item = Result<I::Item, I::Item>;
fn next(&mut self) -> Option<Self::Item> {
match (self.it.next(), self.n) {
(None, _) => None,
(Some(x), 0) => Some(Err(x)),
(Some(x), _) => {
self.n -= 1;
Some(Ok(x))
},
}
}
}
我们也做一个效用函数:
fn take_exactly<I: IntoIterator>(it: I, n: usize) -> TakeExactly<I::IntoIter> {
TakeExactly {
it: it.into_iter(),
n,
}
}
完成后,我们可以轻松收集预期数量的项目:
let x: Result<Vec<_>, _> = take_exactly(vec![5, 4, 3], 2).collect();
assert_eq!(x, Err(3));
let x: Result<String, _> = take_exactly("Rustacean".chars(), 9).collect();
assert_eq!(x, Ok("Rustacean".to_string()));
这是可能的,因为Result
通过委派所有FromIterator
值的集合来实现Ok
,如果找到了第一个错误,则会产生第一个错误。