Die while-Schleife
Eine while-Schleife führt in R ihren Rumpf so lange aus, wie eine Bedingung TRUE bleibt. Wo eine for-Schleife einmal pro Element von etwas läuft, läuft while eine unbekannte Anzahl von Malen - bis sich eine Bedingung ändert:
Drei Teile lassen jede while-Schleife funktionieren, und alle drei sind hier sichtbar:
- Vorbereitung vor der Schleife -
count <- 1gibt der Bedingung etwas zum Prüfen. - Die Bedingung -
count <= 5, gebaut aus den üblichen Vergleichsoperatoren, vor jedem Durchlauf geprüft. - Die Aktualisierung im Rumpf -
count <- count + 1bewegt die Schleife Richtung Ende.
Lösch Teil 3, und die Bedingung ist für immer TRUE: Die Schleife endet nie. Das ist das prägende Risiko von while, und der Rest dieser Seite handelt weitgehend davon, es zu beherrschen.
Die Bedingung wird vor jedem Durchlauf geprüft
while prüft zuerst seine Bedingung und führt dann den Rumpf aus. Daraus folgen zwei Konsequenzen. Ist die Bedingung schon zu Beginn FALSE, läuft der Rumpf null Mal:
Und die Prüfung findet zwischen vollständigen Durchläufen statt, nicht mitten im Rumpf - hat ein Durchlauf begonnen, läuft er bis zum Ende, selbst wenn die Bedingung auf halber Strecke FALSE wird. Musst du mitten im Rumpf aussteigen, ist genau dafür break da (siehe unten).
Ein durchgerechnetes Beispiel: Halbieren bis unter eine Schwelle
Die natürliche Heimat von while ist "weitermachen bis": Du kannst nicht im Voraus wissen, wie viele Durchläufe es braucht, also passt for nicht. Wie oft kann man 1000 halbieren, bevor es unter 1 fällt?
Zehn Halbierungen, endend bei etwa 0,977. Das Muster - eine Zustandsvariable, die der Rumpf schrumpfen lässt, ein Zähler, den er wachsen lässt - deckt einen riesigen Anteil echter while-Schleifen ab: numerische Verfahren, die laufen, bis ein Fehler klein genug ist, Simulationen, die laufen, bis eine Ressource erschöpft ist, Wiederholungsversuche, die weitergehen, bis ein Aufruf gelingt.
repeat + break: R's do-while
R hat kein do-while-Schlüsselwort - keine Schleife, die ihre Bedingung nach dem Rumpf prüft. Aber es hat repeat, das bedingungslos ewig schleift, und break, das jede Schleife sofort verlässt. Setz den break-Test ans Ende eines repeat-Rumpfs, und du hast genau ein do-while gebaut - eine Schleife, deren Rumpf garantiert mindestens einmal läuft:
Der Rumpf wird stets vor dem ersten Test ausgeführt, also wird n mindestens einmal verdoppelt; die Schleife endet bei 128, der ersten Verdopplung über 100. Nutze diese Form, wenn "mach die Sache, dann entscheide, ob du sie nochmal machst" die ehrliche Beschreibung ist - Eingaben lesen, bis sie gültig sind, Stichproben ziehen, bis eine qualifiziert. Ein repeat ohne erreichbares break ist konstruktionsbedingt eine Endlosschleife, also schreib erst das break und füll dann den Rumpf.
break funktioniert in while- und for-Schleifen identisch - es ist der allgemeine "Wir sind hier fertig"-Ausgang und passt natürlich zu if-Anweisungen, die eine Bedingung mitten im Rumpf prüfen.
next in einer while-Schleife
next überspringt den Rest des aktuellen Durchlaufs und springt zurück zur Bedingungsprüfung. Es funktioniert in while genau wie in for - mit einer Falle, die für while spezifisch ist: Kommt der Aktualisierungsschritt nach dem next, bedeutet sein Überspringen, dass die Schleifenvariable nie vorwärtskommt, und du hast eine Endlosschleife gebaut. Setz die Aktualisierung vor das next:
Das gibt die geraden Zahlen 2 bis 10 aus. Verschieb i <- i + 1 unter die next-Zeile, und der erste ungerade Wert würde die Aktualisierung für immer überspringen. In for-Schleifen existiert diese Gefahr nicht (die Schleifenvariable rückt automatisch vor), ein weiterer Grund, for zu bevorzugen, wenn du schlicht eine Sequenz abläufst.
Gegen Endlosschleifen absichern
Jede Endlosschleife ist derselbe Bug: Nichts im Rumpf verändert die Variablen, von denen die Bedingung abhängt - oder verändert sie in die falsche Richtung. Interaktiv kannst du mit Esc oder Strg+C unterbrechen, aber in einem Skript hängt der Prozess einfach. Zwei Gewohnheiten verhindern das.
Erstens: Wenn du die Bedingung schreibst, frag dich sofort "Welche Zeile des Rumpfs bewegt sie Richtung FALSE?" und stell sicher, dass diese Zeile auf jedem Pfad durch den Rumpf läuft (achte auf die next-Falle oben).
Zweitens: Für Schleifen, deren Terminierung du nicht leicht beweisen kannst, füge eine Obergrenze für Iterationen hinzu, damit ein Logikfehler ein diagnostizierbares Ergebnis statt einer eingefrorenen Sitzung liefert. Hier schützt sie eine Collatz-artige Schleife - gerade Zahlen wiederholt halbieren und ungerades x zu 3 * x + 1 machen, bis 1 erreicht ist:
Von 10 aus erreicht die Schleife 1 in 6 Schritten. Erreichte irgendein Startwert nie 1, würde die Klausel steps < 10000 die Schleife trotzdem beenden, und der ausgegebene Zustand würde dir sagen, dass etwas schiefging - eine falsche Antwort, die du sehen kannst, schlägt ein Programm, das nie antwortet. Das verkürzt auswertende && ist hier der richtige Operator: Beide Seiten sind Einzelwerte, und die Absicherung liest sich wie ein Satz.
while vs. for: die Wahl
Die Faustregel dreht sich darum, was du im Voraus weißt:
- Du weißt, worüber du iterierst (Elemente eines Vektors, Zahlen 1 bis n): nimm eine for-Schleife - die Schleifenvariable verwaltet sich selbst.
- Du kennst nur die Abbruchbedingung (bis konvergiert, bis unter Schwelle, bis gültig): nimm
while. - Der Rumpf muss mindestens einmal laufen, bevor irgendein Test Sinn ergibt: nimm
repeatmit einem beendendenbreak.
Wenn du in einer while-Schleife einen manuellen Zähler pflegst, nur um einen Vektor abzulaufen, ist das eine verkleidete for-Schleife - wechsle.
Was du mitnimmst
while (condition) { ... }prüft zuerst, läuft dann - eine falsche Bedingung zu Beginn bedeutet null Durchläufe.- Der Rumpf muss die Bedingung Richtung
FALSEbewegen; das Trio Vorbereitung / Bedingung / Aktualisierung ist die ganze Disziplin. - R hat kein do-while-Schlüsselwort:
repeat { body; if (done) break }ist das Idiom und garantiert mindestens einen Durchlauf. breakverlässt jede Schleife; beinextin einemwhiledie Schleifenvariable vor dem Überspringen aktualisieren, sonst kommt sie nie voran.- Eine Iterationsobergrenze (
&& steps < 10000) verwandelt ein potenzielles Hängen in eine sichtbare, debugbare falsche Antwort.
Als Nächstes: Vektoren - die Datenstruktur, die jede Schleife auf dieser Seite abgelaufen ist, und der Grund, warum viele R-Schleifen ganz verschwinden können.
Häufig gestellte Fragen
Wie funktioniert eine while-Schleife in R?
while (condition) { ... } prüft zuerst die Bedingung und führt den Rumpf nur aus, solange sie TRUE bleibt. Irgendetwas im Rumpf muss die Bedingung irgendwann FALSE machen - typischerweise ein Zähler, der hochgezählt wird, oder ein Wert, der schrumpft - sonst endet die Schleife nie. Ist die Bedingung schon zu Beginn FALSE, läuft der Rumpf null Mal.
Hat R eine do-while-Schleife?
Nicht als Schlüsselwort. Das Idiom lautet repeat { ...body...; if (condition) break } - repeat schleift bedingungslos, sodass der Rumpf garantiert mindestens einmal läuft, und das break am Ende übernimmt die Rolle des do-while-Ausstiegstests.
Wie stoppt man eine Endlosschleife in R?
Interaktiv drückst du Esc (RStudio) oder Strg+C (Terminal), um zu unterbrechen. Um sie von vornherein zu verhindern: Stelle sicher, dass der Rumpf die Variablen der Bedingung bei jedem Durchlauf aktualisiert, und füge eine Obergrenze für Iterationen hinzu - while (working && steps < 10000) -, damit ein Logikfehler eine falsche Zahl statt einer eingefrorenen Sitzung erzeugt.