Das Zippen von Vektoren desselben Typs führt zu unterschiedlichen Typen beim Schließen der Karte
Hintergrund
Bei einem Enum-Variantentyp (nicht kopierbar):
enum AstNode {
Op(Func, Box<AstNode>, Box<AstNode>),
Val(f64),
// others...
}
Versuch, eine Operation über zwei solche Vektoren auszuführen:
fn apply_func_iterative(func: Func, lhs: Vec<AstNode>, rhs: Vec<AstNode>) -> Vec<AstNode> {
lhs.iter().zip(rhs).map(|(&l,r)| apply_func(func,l,r)).collect() // l and r are declared differently!
}
fn apply_func(func: Func, lhs: AstNode, rhs: AstNode) -> AstNode {
// magic happens here!
}
Innerhalb des Verschlusses nehmen die lhs
Elemente den Typ an, l: &AstNode
während die gezippten rhs
Elemente den Typ annehmen l: AstNode
. (Beachten Sie die unterschiedlichen Deklarationen im Verschlusstupel).
Fragen
Warum ist das so?
Gibt es eine Möglichkeit, Elemente eines Vektors nach Wert anstatt nach Referenz zu iterieren? Es scheint, dass dies aufgrund des beobachteten Verhaltens der gezippten Elemente möglich ist.
(In diesem Beispiel führt dieser Unterschied zu einer leichten Seltsamkeit bei der Syntaxdeklaration, aber in der Praxis bin ich beim Übergeben der Referenzvariablen an eine Funktion auf den Kreditprüfer gestoßen.)
Haftungsausschluss: Ich bin ziemlich neu bei Rust
Antworten
Die Iterator::zipMethode macht nichts Besonderes, sondern kombiniert einfach beide Iteratoren. Sie stellen fest, dass lhs.iter()
eine Iterator<&AstNode>
Weile rhs
eine Iterator<AstNode>
( &
gegen Nicht- &
) ergibt .
Gibt es eine Möglichkeit, Elemente eines Vektors nach Wert anstatt nach Referenz zu iterieren? Es scheint, dass dies aufgrund des beobachteten Verhaltens der gezippten Elemente möglich ist.
Ja, es gibt eine Möglichkeit, dieses Verhalten zu steuern. Der Schlüssel ist zu bemerken, dass zip()
das Argument rhs
das IntoIterator
Merkmal implementieren muss . Intern zip()
wird aufgerufen rhs.into_iter()
, um einen Iterator daraus zu erhalten. Das herkömmliche Verhalten ist , dass .iter()nur leiht sich die Quelle und daher nur Verweise auf seine Werte liefern kann. Während verbraucht oder "übernimmt" die Quelle und kann eigene Werte liefern..into_iter()
Wenn Sie diese kombinieren, können Sie lhs.into_iter().zip(rhs)
einen Iterator über Werte abrufen (AstNode, AstNode)
oder lhs.iter().zip(rhs.iter())
einen Iterator über Referenzen abrufen (&AstNode, &AstNode)
.