扩展所有迭代器<item e =“”>&gt;转换类型

时间:2017-11-25 15:49:29

标签: generics rust iterator traits rust-result

我尝试为Iterator<Item = Result<Type, E>>通用的所有E实施扩展特征,以生成另一个Iterator而不是Result<OtherType, E>,其中的错误来自Type -> OtherType转发原件。

问题是,转换f(t: Type) -> Result<OtherType, ConcreteError>可能会失败(函数为E

因此,迭代可能会从底层迭代器返回pub struct A; pub struct B; pub struct CongreteError; fn transform(a: A) -> Result<B, CongreteError> { Ok(B {}) } pub struct ExtensionIter<E>(Box<Iterator<Item = Result<A, E>>>); impl<E> Iterator for ExtensionIter<E> { type Item = Result<B, E>; fn next(&mut self) -> Option<Self::Item> { match self.0.next() { Some(Ok(a)) => Some(transform(a)), Some(Err(e)) => Some(Err(e)), None => None, } } } pub trait Extension<E> { fn extend(self) -> ExtensionIter<E>; } impl<E, I> Extension<E> for I where I: Iterator<Item = Result<A, E>>, { fn extend(self) -> ExtensionIter<E> { ExtensionIter(Box::new(self)) } } fn main() { let v: Vec<A> = vec![]; for element in v.iter().extend() { match element { Ok(b) => {} Err(e) => {} } } } (泛型)或具体的错误类型,这当然是不可能的。

如何实现这个?

一个最小的例子:

error[E0308]: mismatched types
  --> src/main.rs:16:33
   |
16 |             Some(Ok(a)) => Some(transform(a)),
   |                                 ^^^^^^^^^^^^ expected type parameter, found struct `CongreteError`
   |
   = note: expected type `std::result::Result<_, E>`
              found type `std::result::Result<_, CongreteError>`
   = help: here are some functions which might fulfill your needs:
           - .map_err(...)
           - .or(...)
           - .or_else(...)

error[E0310]: the parameter type `I` may not live long enough
  --> src/main.rs:32:23
   |
27 | impl<E, I> Extension<E> for I
   |         - help: consider adding an explicit lifetime bound `I: 'static`...
...
32 |         ExtensionIter(Box::new(self))
   |                       ^^^^^^^^^^^^^^
   |
note: ...so that the type `I` will meet its required lifetime bounds
  --> src/main.rs:32:23
   |
32 |         ExtensionIter(Box::new(self))
   |                       ^^^^^^^^^^^^^^

error[E0599]: no method named `extend` found for type `std::slice::Iter<'_, A>` in the current scope
  --> src/main.rs:38:29
   |
38 |     for element in v.iter().extend() {
   |                             ^^^^^^
   |
   = note: the method `extend` exists but the following trait bounds were not satisfied:
           `std::slice::Iter<'_, A> : Extension<_>`
           `&std::slice::Iter<'_, A> : Extension<_>`
           `&mut std::slice::Iter<'_, A> : Extension<_>`
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `extend`, perhaps you need to implement it:
           candidate #1: `Extension`

playground

错误:

CREATE PROCEDURE search
@id INT

AS
BEGIN
SET NO COUNT ON;
SELECT  cteachID,
        cfname,
        cmname,
        clname
FROM tbl_teacher
WHERE cteachID = @id
END

1 个答案:

答案 0 :(得分:3)

高度建议阅读The Rust Programming Language。它充满了新Rust程序员应该知道的信息。

  

可能会返回E [...]或具体的错误类型

Rust的一个令人兴奋的功能是enums。枚举允许您创建可以是多种其他类型之一的类型。在这种情况下,我们可以将枚举定义为基础错误或我们自己的错误:

pub enum ExtensionError<E> {
    Original(E),
    Concrete(ConcreteError),
}

然后,这只是从一种类型映射到另一种类型的问题:

pub struct A;
pub struct B;
pub struct ConcreteError;

fn transform(_: A) -> Result<B, ConcreteError> {
    Ok(B {})
}

pub struct ExtensionIter<I>(I);
pub enum ExtensionError<E> {
    Original(E),
    Concrete(ConcreteError),
}

impl<I, E> Iterator for ExtensionIter<I>
where
    I: Iterator<Item = Result<A, E>>,
{
    type Item = Result<B, ExtensionError<E>>;

    fn next(&mut self) -> Option<Self::Item> {
        match self.0.next() {
            Some(Ok(a)) => Some(transform(a).map_err(ExtensionError::Concrete)),
            Some(Err(e)) => Some(Err(ExtensionError::Original(e))),
            None => None,
        }
    }
}

pub trait Extension: Iterator {
    fn extend(self) -> ExtensionIter<Self>
    where
        Self: Sized,
    {
        ExtensionIter(self)
    }
}

impl<I: Iterator> Extension for I {}

fn main() {
    let v: Vec<Result<A, ()>> = vec![];
    for element in v.into_iter().extend() {
        match element {
            Ok(_) => {}
            Err(_) => {}
        }
    }
}