Rost gestapelt optional in während lassen
Ich bin wirklich neu in Rost und während ich die Raschelübungen durchging, fand ich etwas, das ich in Bezug auf gestapelte Optionen nicht vollständig verstehe.
Gegeben den folgenden Code:
let vector = vec![Some(24), None, Some(42)];
let mut iter = vector.iter();
while let Some(Some(number)) = iter.next() {
println!("Number: {}", number);
}
Ich würde die folgende Ausgabe erwarten:
Number: 24
Number: 42
Aber ich denke, sobald Rost auf Nonedie while-Schleife trifft , wird sie beendet und nur die 24 gedruckt
Was wäre der idiomatischste Rostcode, um optionale Werte zu iterieren und zu entpacken? Das nächste, das ich bekam, würde ungefähr so aussehen:
let mut iter = vector.iter();
while let Some(iterNext) = iter.next() {
if let Some(num) = iterNext {
println!("Number: {}", num);
}
}
Oder Sie können dies auch tun, indem Sie die Existenz in einer for-Schleife überprüfen:
for opt in &vector {
if opt.is_some() {
println!("Number: {}", opt.unwrap());
}
}
Antworten
Ich würde die folgende Ausgabe erwarten: [...]
Eine whileSchleife, die auf eine falsche Bedingung stößt, wird beendet - aber das ist nicht spezifisch für Rust, sondern nur so, wie whileSchleifen funktionieren.
Eine idiomatische Lösung würde wahrscheinlich Ihre letzten beiden Schnipsel kombinieren:
for opt in &vector {
if let Some(num) = opt {
println!("Number: {}", num);
}
}
Nur eine einfache forSchleife mit einem if let, kein Auspacken erforderlich.
Eine andere idiomatische Variante ist die Verwendung von Iteratoradaptern:
vector
.iter()
.filter_map(|opt| opt.as_ref())
.for_each(|num| println!("{}", num));
Beachten Sie, dass wir hier verwenden könnten filter(Option::is_some), aber dann würden wir mit Optionen belassen und müssten verwenden unwrap(), um zu den Werten zu gelangen. Hier filter_map()kommt es zum Tragen: Es filtert die SomeWerte (nach Anwendung der Kartenfunktion) und extrahiert gleichzeitig die darin enthaltenen Werte. opt.as_ref()dient zur trivialen Konvertierung &Option<T>, die sich aus der Iteration eines Vektors von Optionen durch Bezugnahme ergibt, auf Option<&T>die die filter_mapRückgabe erwartet wird.
Eine andere gute Möglichkeit, diesen Code zu schreiben, ist
for num in vector.iter().flatten() {
println!("{}", num);
}
Die flatten()Methode auf einem Iterator behandelt jedes Element des Iterators als Iterator und gibt einen Iterator über alle diese miteinander verketteten Iteratoren zurück. Optionist ein Iterator, der ein Element liefert, wenn es ist Someoder keines None, also flatten()genau das, was wir hier wollen.
Natürlich können Sie dies auch mit schreiben for_each(), aber für Code mit Nebenwirkungen bevorzuge ich im Allgemeinen forSchleifen.