当迭代器中的项目多于预期时返回错误

时间:2017-09-20 12:34:44

标签: rust

Optionok_orSome映射到OkNone映射到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中?运算符和方法链的简洁性。

1 个答案:

答案 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,如果找到了第一个错误,则会产生第一个错误。

Playground