2015-08-22 12 views
6

ich den Wald nicht für die Bäume sehen kann, aber ich frage mich, wie kann ich eigentlich meine Methoden entwerfen nicht gegen harte Sammlungstypen zu arbeiten, aber gegen Iteratoren statt. Betrachten Sie diese Methode.Wie verwende ich den Iterator Merkmal generic APIs zu bauen

pub fn print_strings(strings: Vec<String>) { 
    for val in strings.iter() { 
     println!("{}", val); 
    } 
} 

Offensichtlich fällt diese kurz, wenn ich, dass ein mit verwenden möchten HashSet oder HashMap.

Also habe ich versucht, dies:

use std::collections::*; 

fn main() { 
    let strings = vec!("Foo", "Bar"); 

    let mut more_strings = HashMap::new(); 
    more_strings.insert("foo", "bar"); 
    more_strings.insert("bar", "foo"); 

    print_strings(&strings.iter()); 
    print_strings(&more_strings.values()) 
} 

fn print_strings(strings: &Iterator<Item=&str>) { 
    for val in strings { 
     println!("{}", val); 
    } 
} 

Playpen

http://is.gd/EYIK11

Leider (auch langwieriger Compiler-Fehler zu sehen), dies scheint nicht den Trick zu tun. Was vermisse ich?

+0

Bitte fügen Sie die Fehlermeldung ein. Es zeigt Ihnen, was mit Ihrer Implementierung nicht stimmt.Vielleicht möchten Sie überprüfen, was der Typ von Iterator :: Item für den Iterator ist, den Sie haben. – Shepmaster

+0

Ich denke nicht, dass das eine gute Idee ist, da es ziemlich lang ist. Sie können auf den Laufstall-Link klicken, um die gesamte Compiler-Fehlerausgabe anzuzeigen. – Christoph

+0

Wenn Sie '.iter()' auf einem 'Vec ' aufrufen, erhalten Sie einen 'Iterator '. Wenn Sie '.iter()' auf einem 'Vec <&str>' aufrufen, erhalten Sie einen 'Iterator ', nicht einen 'Iterator '. Sie sollten sich die '.cloned()' Methode für 'Iterator' anschauen, damit Ihr Problem gelöst werden kann. – Adrian

Antwort

7

Noch besser ist, können Sie

fn print_strings<Iterable>(strings: Iterable) 
    where Iterable: IntoIterator, 
      Iterable::Item: AsRef<str> 
{ 
    for val in strings { 
     println!("{}", val.as_ref()); 
    } 
} 

(Kudos Shepmaster für die Verbesserung.) Tun

Dies bedeutet, dass Sie dies mit &mut Iterator s für dynamische Dispatch oder Beton Iterator nennen kann oder Sammlungsarten für den statischen Versand. Ferner kann der Iteratortyp alles sein, was einfach in &str konvertiert werden kann, was &str, &&str und sogar String umfasst, aber nicht darauf beschränkt ist.

print_strings(&strings); 
print_strings(strings.iter().map(|s| s.to_owned())); 
print_strings(vec![&&&&"xyz"]); 
print_strings(strings); 
print_strings(more_strings.values()); 
4

Wenn Sie .iter() auf einem Vec<T> aufrufen, erhalten Sie eine Iterator<Item=&T>. Wenn Sie also .iter() auf einer Vec<&str> anrufen, erhalten Sie eine Iterator<Item=&&str>, keine Iterator<Item=&str>. Sie sollten die .cloned() Methode für Iterator betrachten, es sollte helfen, Ihr Problem zu lösen.

Beachten Sie außerdem, dass Sie, um einen Iterator zu durchlaufen, in der Lage sein müssen, ihn zu mutieren (entweder besitzen Sie den Iterator oder haben einen veränderbaren Verweis darauf). Es ist also nutzlos, nur einen unveränderlichen Bezug darauf zu haben. Ich würde empfehlen, den Iterator-Wert in print_strings zu verschieben, anstatt ihn als Referenz zu übergeben. Wenn Sie dafür Merkmalsobjekte verwenden wollen, können Sie das mit Box tun, aber es könnte einfacher sein, print_strings einfach zu einer generischen Funktion zu machen.

4

playpen
Das erste, was ist, dass Sie Iterator<Item=&str> erwar, aber es ist eigentlich Iterator<Item=&&str>.
Dann versuchen Sie .iter() aufzurufen, aber Iterator hat diese Methode nicht. Sie können einfach entfernen .iter() Anruf und erhalten (und senden OFC) &mut Iterator<...>, um for Schleife funktioniert zu bekommen (for Schleife braucht etwas, das implementiert IntoIterator und &mut Iterator ist das Ding).
Fügen Sie Lebenszeiten hinzu und Sie sind fertig! :)
Außerdem empfehle ich statische Versand verwenden. Sie können es in dem Beispiel sehen, das ich zur Verfügung gestellt habe.

+0

Ok, dieser Laufstall macht alles perfekt. Bezüglich des statischen Versands habe ich einige Tastenanschläge für das Beispiel gespeichert: P – Christoph

Verwandte Themen