2015-07-13 19 views
7

Ich finde es seltsam, dass Iterator::take_while Besitz des Iterators übernimmt. Es scheint ein nützliches Merkmal zu sein, die ersten Elemente zu verwenden, die eine bestimmte Funktion erfüllen, aber den Rest der Elemente, die im ursprünglichen Iterator verfügbar sind, übrig lassen.Warum übernimmt Iterator :: take_while den Iterator?

Ich verstehe, dass dies mit einer faulen Implementierung von take_while inkompatibel ist, aber immer noch nützlich fühlt. War das nur als nicht sinnvoll genug, um in die Standardbibliothek aufgenommen zu werden, oder gibt es ein anderes Problem, das ich nicht sehe?

Antwort

9

Alle Iteratoradapter verwenden den ursprünglichen Iterator aus Effizienzgründen als Wert. Wenn Sie den Zugriff auf den ursprünglichen Iterator beibehalten möchten, können Sie by_ref verwenden. Dies führt zu einer Dereferenzierungsebene, aber der Programmierer wählt in die zusätzliche Arbeit zu entscheiden, wenn die Funktion benötigt wird:

fn main() { 
    let v = [1, 2, 3, 4, 5, 6, 7, 8]; 
    let mut i1 = v.iter(); 
    for z in i1.by_ref().take_while(|&&v| v < 4) { 
     println!("Take While: {}", z); 
    } 

    for z in i1 { 
     println!("Rest: {}", z); 
    } 
} 

Hat der Ausgang

Take While: 1 
Take While: 2 
Take While: 3 
Rest: 5 
Rest: 6 
Rest: 7 
Rest: 8 

Haben Sie beachten Sie, dass 4 fehlte? Das ist so, weil take_while einmal einen Wert auswählt und beschließt, ihn nicht zu verwenden, gibt es keinen Platz dafür, ihn "zurückzulegen". Putting es zurück würde erfordern mehr Lagerung und Langsamkeit als immer benötigt wird.

Ich habe die itertools crate verwendet, um solche Fälle zu behandeln, speziell take_while_ref.