Slice und iter () gleichzeitig

7

Ich versuche herauszufinden, warum das nicht funktioniert ( Spielplatz ):

%Vor%

Fehler:

%Vor%

Aber das funktioniert:

%Vor%

Bitte erläutern Sie, wie Vektoren in Rust arbeiten und den Unterschied, wenn ich iter() .

    
Abhijay Ghildyal 09.12.2016, 13:03
quelle

3 Antworten

13

Kurz gesagt : Sie haben wahrscheinlich die Rangfolge der Operatoren falsch verstanden:

%Vor%

Ist gleich:

%Vor%

Und da zip() etwas erwartet, das IntoIterator implementiert, schlägt der Aufruf fehl, da ein Verweis auf diesen Iteratortyp dieses Merkmal nicht implementiert.

Vollständige Erklärung

Versuchen wir, die Fehlermeldung zu verstehen! Natürlich sehen wir uns zuerst den ersten Fehler an:

%Vor%

Wow, das ist ein ziemlicher Bissen. Aber wir können sehen, dass einige merkmalsgebundene Anforderungen der Funktion zip() wird verletzt. Schauen wir uns die Signatur der Funktion an:

%Vor%

Wichtig ist das Argument other (Typ U ). U muss IntoIterator sein. Dieses Merkmal ist für einige Arten implementiert ... lasst uns prüfen, welchen Typ wir in zip() übergeben wollen:

%Vor%

Um das vollständig zu analysieren, müssen wir etwas verstehen, aber ich werde versuchen, es zu durchbrechen. Lassen Sie uns zunächst die Rangfolge der Operatoren durch Einfügen weiterer Klammern unterscheiden. Das obige Code-Snippet entspricht:

%Vor%
  1. Ein Ausdruck foo[bar] desugares to *::std::ops::Index::index(&foo, bar) . Dies ist der komplexeste Teil hier, aber wenn Sie in der Dokumentation nachsehen, hat der Ausdruck b[1..b.len()] den Typ [i32] .

  2. Bei diesem Typ rufen Sie iter() auf gibt einen Typ Iter<_, _> zurück, der der Iteratortyp für Slices ist.

  3. Jetzt die & : Sie leihen diese Iter<_, _> Sache, was in &Iter<_, _> resultiert.

Und hey, das stimmt mit der Fehlermeldung überein! Schau dir die letzte Notiz an:

%Vor%

Also ... was erfüllt die Eigenschaft IntoIterator ? Zum einen implementiert jeder Typ, der Iterator implementiert (z. B. Iter<_, _> ) auch IntoIterator . Sie können also & im Ausdruck entfernen und es funktioniert!

Aber wir können es noch besser machen! IntoIterator ist auch für &[T] implementiert, also kannst du auch einfach .iter() entfernen und es funktioniert!

Arbeitscode

%Vor%

Hinweis : Ich habe auch die oberen Grenzen der Bereiche entfernt, um sie halboffen zu machen, wie Paolo Falabella vorgeschlagen hat .

    
Lukas Kalbertodt 09.12.2016, 13:41
quelle
5

Ihre erste Version hat ein Problem mit der Vorrangstellung des Operators: &a[1..a.len()].iter() wendet zuerst iter() an und nimmt dann eine Referenz darauf, die mit einem Verweis auf std::slice::Iter endet.

Wie Sie in den Dokumenten für Iter sehen können, gibt es ein impl Iterator für Iter , aber nicht für &Iter . Dies ist es, was der erste Fehler versucht zu sagen: (Schauen Sie sich den Teil an, der sagt: &std::slice::Iter<'_, {integer}> ist kein Iterator).

Vereinfacht ein bisschen, können Sie haben:

%Vor%     
Paolo Falabella 09.12.2016 13:45
quelle
2

Iterator::zip erwartet etwas, das IntoIterator implementiert.

Anstatt ein Iterator zu übergeben, geben Sie eine Referenz an Iterator . Iterator s mutieren und eine Referenz ist nicht ausreichend.

Sie können dies beheben, indem Sie Klammern verwenden, um zu verdeutlichen, was Sie versuchen, eine Referenz von

zu erhalten %Vor%     
Reece45 09.12.2016 13:38
quelle

Tags und Links