Schleifen in Rust
Rust kennt drei Arten, Code zu wiederholen: loop, while und for. Auf dieser Seite geht es um loop, die einfachste und direkteste der drei Schleifen. Sie wiederholt sich endlos, bis du ihr sagst, dass sie aufhören soll.
Eine einfache loop-Schleife
Abschnitt betitelt „Eine einfache loop-Schleife“fn main() { let mut count = 0;
loop { count += 1; println!("{count}");
if count == 3 { break; } }}Ausgabe:
123Von allein hört loop nie auf – erst break beendet die Schleife. Ohne das if count == 3 { break; } würde dieses Programm endlos weiterzählen.
Einen Wert aus einer Schleife zurückgeben
Abschnitt betitelt „Einen Wert aus einer Schleife zurückgeben“Das hier kann loop, aber nicht while und for: Du kannst hinter break einen Wert schreiben. Dieser Wert wird dann zum Ergebnis der ganzen Schleife:
fn main() { let mut count = 0;
let result = loop { count += 1; if count == 10 { break count * 2; // anhalten und einen Wert zurückgeben } };
println!("{result}");}Ausgabe:
20Das ist praktisch für Fälle wie „Versuch es so lange, bis es klappt, und gib mir dann das Ergebnis“. Dieses Muster begegnet dir in echtem Code öfter, als du denkst.
Achte auf das Semikolon nach der schließenden } der Schleife. Die ganze loop { ... } ist die rechte Seite von let result = ...;. Deshalb braucht die let-Anweisung am Ende ihr ; – genau wie bei let x = 5;.
Warum loop statt while true?
Abschnitt betitelt „Warum loop statt while true?“Wenn du aus einer anderen Sprache kommst, schreibst du eine Endlosschleife vielleicht als while true { ... }. Das funktioniert in Rust, aber der Compiler warnt dich:
warning: denote infinite loops with `loop { ... }` --> src/main.rs:5:5 |5 | while true { | ^^^^^^^^^^ help: use `loop`Die Warnung sagt: Kennzeichne Endlosschleifen mit loop { ... }. Dabei geht es nicht nur um Stil. Rust weiß, dass der Rumpf einer loop immer läuft und dass sie nur über ein break verlassen werden kann. Bei while true nimmt Rust das nicht an, weil es sich den Wert der Bedingung nicht anschaut. Das macht einen echten Unterschied, wenn eine Variable ihren Wert erst in der Schleife bekommt:
fn main() { let mut n = 1; let answer; // noch kein Wert
loop { if n * n > 50 { answer = n * n; // direkt vor dem Verlassen setzen break; } n += 1; }
println!("Die erste Quadratzahl über 50 ist {answer}");}Ausgabe:
Die erste Quadratzahl über 50 ist 64Mit loop erkennt Rust, dass println! nur über dieses break erreicht werden kann. answer ist also immer gesetzt. Ersetzt du loop durch while true, bekommst du error[E0381]: used binding answer is possibly-uninitialized – die Variable ist möglicherweise nicht initialisiert. Der Compiler glaubt, die Schleife könnte enden, ohne das if überhaupt auszuführen.
In der Praxis ist die sauberste Version dieses Programms ein break mit Wert, wie du es oben gesehen hast: let answer = loop { ... break n * n; ... };. So oder so ist die Lehre dieselbe: Wenn du „für immer, bis ich abbreche“ meinst, schreib loop.
Wann du loop verwendest
Abschnitt betitelt „Wann du loop verwendest“loop ist die richtige Wahl, wenn du vorher nicht weißt, wie oft du etwas wiederholen wirst. Du wartest also darauf, dass eine Bedingung eintritt, statt einen Bereich oder eine Liste durchzuzählen. Zum Zählen oder um eine Collection zu durchlaufen, lesen sich while und for (die als Nächstes kommen) meist besser.
Übungen
Abschnitt betitelt „Übungen“1. Countdown zum Start
Abschnitt betitelt „1. Countdown zum Start“Gib mit loop einen Countdown von 5 bis 1 aus und danach Start!. Tipp: Beginne mit let mut n = 5; und brich mit break ab, sobald n bei 0 ankommt.
Lösung anzeigen
fn main() { let mut n = 5;
loop { if n == 0 { break; } println!("{n}..."); n -= 1; }
println!("Start!");}Ausgabe:
5...4...3...2...1...Start!Die Prüfung kommt zuerst. Wenn n also 0 ist, stoppt die Schleife, bevor 0... ausgegeben wird.
2. Die erste Zweierpotenz über 1000
Abschnitt betitelt „2. Die erste Zweierpotenz über 1000“Beginne bei 1 und verdopple immer weiter. Hol dir mit break und einem Wert die erste Zahl über 1000, und zähle, wie viele Verdopplungen das gebraucht hat. Tipp: Halte einen mut-Zähler außerhalb der Schleife und schreib let power = loop { ... };.
Lösung anzeigen
fn main() { let mut value = 1; let mut doublings = 0;
let power = loop { value *= 2; doublings += 1; if value > 1000 { break value; } };
println!("{power} nach {doublings} Verdopplungen");}Ausgabe:
1024 nach 10 Verdopplungenbreak value; beendet die Schleife und übergibt value an power. Der Zähler lebt außerhalb der Schleife und behält deshalb seinen Wert, auch nachdem sie zu Ende ist.
Zusammenfassung
Abschnitt betitelt „Zusammenfassung“loopwiederholt sich endlos, bis einbreakdie Schleife stoppt – sorg immer dafür, dass es eines gibt.break wert;beendet die Schleife und gibtwertals Ergebnis des ganzen Schleifen-Ausdrucks zurück.- Schreib
loop, nichtwhile true: Rust weiß, dass der Rumpf einerloopimmer läuft, und kann so deine Variablen besser prüfen. - Greif zu
loop, wenn du etwas „so lange, bis etwas passiert“ wiederholst – nicht, wenn du eine bekannte Anzahl von Durchläufen zählst.
Kurzer Check
Abschnitt betitelt „Kurzer Check“Kurzer Check
1. Was verhindert, dass eine einfache loop-Schleife endlos läuft?
2. Was bewirkt break count * 2; in einer Schleife?
3. Wann ist loop laut dieser Seite die bessere Wahl als while oder for?
4. Was passiert, wenn du in Rust while true { ... } schreibst?
Punkte: 0 / 4
Weiterlesen
Abschnitt betitelt „Weiterlesen“- Wiederholung mit Schleifen – Das Rust-Buch: die offizielle Einführung in
loop,whileundfor. - Rückgabe von Werten aus Schleifen – Das Rust-Buch: ein kurzer Abschnitt über
breakmit einem Wert. - loop – Rust by Example (auf Englisch): ausführbare Beispiele für
loop,breakundcontinue. - Returning from loops – Rust by Example (auf Englisch): noch ein kleines Beispiel für eine Schleife, die einen Wert zurückgibt.
- Das Schlüsselwort
loop– Doku der Standardbibliothek (auf Englisch): eine kompakte Referenz dazu, wieloopundbreakzusammenarbeiten.