2015-06-13 5 views
7

Ich habe den folgenden Code, der nicht kompiliert.Wie nach zwei Zip-Ketten umzukehren

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); 
} 

Got Fehler wie folgt:

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) 

Mein Verständnis ist rev() Methode in Iterator definiert wird, wo sie implementiert Merkmal DoubleEndedIterator

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

Auch Zip implementiert diese Eigenschaft:

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

So ist das Problem Chain implementiert ExactSizeIterator nicht. Aber wie arbeite ich das an?

Ich versuchte .take() für beide Ketten hinzuzufügen, um die Art zu Take zu konvertieren, die ExactSizeIterator implementiert, aber nehmen nicht DoubleEndedIterator nicht implementiert.

Beachten Sie, dass dies ein vereinfachtes Beispiel ist. In Wirklichkeit kann ich nicht beide Ketten zuerst umkehren und dann den Reißverschluss machen.

Antwort

7

Sie suchen nach dem folgenden impl (Spoiler: es existiert nicht):

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

Ein ExactSizeIterator darf nur eine Methode implementieren, len(&self). Die Idee hinter einer hypothetischen Implementierung wäre also, beide Längen so zu summieren, dass chain_a_b.len() == a.len() + b.len().

Die reason it doesn't exist ist, dass Rust nicht garantieren kann, dass dieser Zusatz (usize + usize) nicht überläuft. So verbietet es es. Es klingt ein bisschen streng, aber das ist leider der momentane Stand.

Schlechter: selbst wenn dieses Impl tatsächlich existierte, würden Sie in der Tatsache rennen, dass Chars kein ExactSizeIterator ist, also würde es immer noch nicht funktionieren.

Eine Alternative (wahrscheinlich nicht die einzige) wäre, die Ketten in einem Vektor zu sammeln. Schlecht wegen der Speicherzuordnung, aber wenn es sich nicht um einen Perf-Engpass handelt, könnte sich der Kompromiss lohnen.

Verwandte Themen