2017-11-25 24 views
0

변환합니다.모든 반복자를 확장 <항목 = <Type, E> 결과는> 원본 오류가 전달되는 경우, 다른 <code>Iterator</code><code>Result<OtherType, E></code> 이상을 생성하기 위해, 나는 <code>E</code>는 일반적인 모든 <code>Iterator<Item = Result<Type, E>></code>에 대한 확장 된 특성을 구현하기 위해 노력하고있어 유형

문제는 변환 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) => {} 
     } 
    } 
} 
,

playground

오류 :

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` 

답변

3

나는 매우가 The Rust Programming Language을 읽어 보시기 바랍니다 . 새로운 Rust 프로그래머가 알아야 할 정보로 가득합니다.

는 반환 할 수 있습니다 E [...] 또는 녹의 흥미로운 기능의

하나는 enums있는 구체적인 오류 유형. 열거 형을 사용하면 여러 다른 유형 중 하나 일 수있는 유형을 작성할 수 있습니다. 책을 언급에 대한

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(_) => {} 
     } 
    } 
} 
+0

감사 : 그럼 한 유형에서 다른 유형으로 매핑 단지 문제

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

:이 경우, 우리는 기본 오류 또는 우리 자신이 될하는 열거를 정의 할 수 있습니다 . 저는 2 년 동안 Rust 프로그래머였으며 여러 번 읽었습니다. 방금 결과가 '(enum 도우미없이) 반환하는 방법이있을 것이라고 생각했습니다. – musicmatze

+0

감사합니다. 실제 코드를보고 싶다면 : https://github.com/matthiasbeyer/imag/pull/1163 – musicmatze