2015-06-13 17 views
7

Ho il seguente codice che non viene compilato.Come invertire dopo zip due catene

fn main() { 
    let a = 
    "123" 
    .chars() 
    .chain("4566".chars()) 
    .zip(
     "bbb" 
     .chars() 
     .chain("yyy".chars())) 
    .rev() 
    .map(|x, y| y) 
    .collect::<String>(); 
    println!("Hello, world! {}", a); 
} 

errore Got come segue:

src/main.rs:37:10: 37:15 error: the trait `core::iter::ExactSizeIterator` is not implemented for the type `core::iter::Chain<core::str::Chars<'_>, core::str::Chars<'_>>` [E0277] 
src/main.rs:37   .rev() 
         ^~~~~ 
src/main.rs:37:10: 37:15 error: the trait `core::iter::ExactSizeIterator` is not implemented for the type `core::iter::Chain<core::str::Chars<'_>, core::str::Chars<'_>>` [E0277] 
src/main.rs:37   .rev() 
         ^~~~~ 
src/main.rs:38:10: 38:23 error: type `core::iter::Rev<core::iter::Zip<core::iter::Chain<core::str::Chars<'_>, core::str::Chars<'_>>, core::iter::Chain<core::str::Chars<'_>, core::str::Chars<'_>>>>` does not implement any method in scope named `map` 
src/main.rs:38   .map(|x, y| y) 

La mia comprensione è rev() metodo è definito in Iterator esempio dove implementa tratto DoubleEndedIterator

fn rev(self) -> Rev<Self> where Self: DoubleEndedIterator { ... } 

anche Zip implementa questa caratteristica:

impl<A, B> DoubleEndedIterator for Zip<A, B> where B: DoubleEndedIterator + ExactSizeIterator, A: DoubleEndedIterator + ExactSizeIterator 

Quindi il problema è Chain non implementa ExactSizeIterator. Ma come posso aggirare questo?

Ho provato ad aggiungere .take() per entrambe le catene per convertire il tipo in Take che implementa ExactSizeIterator, ma Take non implementa DoubleEndedIterator.

Nota questo è un esempio semplificato. In realtà non posso invertire prima entrambe le catene e poi fare lo zip.

risposta

7

Stai cercando il seguente impl (spoiler: non esiste):

impl<A, B> ExactSizeIterator for Chain<A, B> 
    where A: ExactSizeIterator, B: ExactSizeIterator { ... } 

Un ExactSizeIterator deve implementare un solo metodo, len(&self). Quindi l'idea alla base di un'ipotetica implementazione sarebbe quella di sommare entrambe le lunghezze in modo che chain_a_b.len() == a.len() + b.len().

Il reason it doesn't exist è che Rust non può garantire che questa aggiunta (usize + usize) non trabocchi. Così lo proibisce. Sembra un po 'severo, ma questo è lo status quo per ora, sfortunatamente.

Peggio ancora: anche se questo impl effettivamente esistesse, si verificherebbe che Chars non è un ExactSizeIterator, quindi non funzionerebbe ancora.

Un'alternativa (probabilmente non l'unica) sarebbe quella di raccogliere le catene in un vettore. Cattivo a causa dell'allocazione di memoria, ma se non è un collo di bottiglia perf potrebbe valere il compromesso.