Ruby/Schleife
Syntax
Schlüsselwörter
Inhaltsverzeichnis
Schleifen
Schleifen sind Kontrollstrukturen, die einen Code mehrmals hintereinander ausführen. Mit ihnen kann man Arrays oder andere Collections durchlaufen, aber auch Prozesse, die im Programm regelmäßig ablaufen sollen (Tastenabfragen, Bewegen der Events, Neuanzeigen der Grafik usw.), wiederholen. Je nach Einsatzzweck gibt es in Ruby verschiedene Schleifentypen. In den meisten Fällen ist aber der Einsatz von Iteratoren, komplexe Methoden die oftmals auf Schleifen basieren, eleganter.
Die grundlegenden Schleifen in Ruby bestehen immer aus einer Laufbedingung und einen Schleifenkörper. Die Laufbedingung ist ein Code, der im Idealfall einen boolschen Wert (wahr oder falsch) zurückgibt. Je nach Wahrheitswert der Laufbedingung wird der Schleifenkörper ausgeführt, oder die Schleife verlassen. Ruby akzeptiert jedoch nahezu alles als Parameter für Bedingungen. So z.B.:
a = if (nil) then 3 elsif (5) then 4 else 7 end Kernel.print(a) #=> 5
Lokale Variablen, die in einer Schleife definiert werden, dürfen auch außerhalb der Schleife verwendet werden. Bei Iteratoren gilt dies nicht.
while
Die While-Schleife, im Deutschen auch Solange-Schleife genannt, führt ihren Schleifenkörper solange aus, wie ihre Laufbedingung wahr ist.
Eine While-Schleife beginnt mit dem Schlüsselwort while. Darauf folgt die Laufbedingung. Optional darf ein do folgen. Das do ist erforderlich, will man den Schleifenkörper in der selben Zeile wie Laufbedingung schreiben. Andernfalls erfolgt nach der Laufbedingung ein Zeilenumbruch. Der Schleifenkörper wird durch das while ... do und end eingegrenzt.
a = 1 print "Schleife beginnt" while a < 10 do print a a = a + 1 end print "Schleife beendet"
In diesem Beispielcode wird eine Variable auf den Wert 1 gesetzt. Danach beginnt eine While-Schleife. Es erfolgt die Abfrage der Laufbedingung. Da 1 < 10 ist, springt der Interpreter in den Schleifenkörper und führt den Code zwischen der while-Zeile und der end-Zeile aus. Danach springt der Code zurück in die Laufbedingung und prüft erneut, ob a kleiner als 10 ist. Der Vorgang wiederholt sich solange, bis die Laufbedingung einen unwahren Wert zurückgibt (a also größer gleich 10 ist). Dann springt der Code in die Anweisung unter das end (verlässt also die Schleife).
Will man nur eine Anweisung wiederholen, so kann man die While-Schleife auch an das Ende der Zeile anhängen (diesmal ist das do aber verboten!).
a = 1 print "Schleife beginnt mit Wert a=1" a = a + 1 while a < 10 print "Schleife endet mit Wert a=10"
Nun ist der Schleifenkörper also die Anweisung vor dem while-Schlüsselwort.
Manchmal ist es erforderlich, dass eine Schleife mindestens ein Mal ausgeführt wird. Ist die Laufbedingung aber schon vor dem ersten Durchlauf unwahr, so wird die Schleife nicht ausgeführt. Setzt man die Anweisung in einen begin...end-Block und hängt das While ans Ende des Blocks, so wird die Schleife mindestens ein Mal durchlaufen - selbst dann wenn die Laufbedingung unwahr ist.
a = 10 begin a = a + 1 print a end while a < 10
Hier wird also erst der Schleifenkörper ausgeführt, und danach die Laufbedingung überprüft. Ist sie unwahr, wird die Schleife verlassen, andernfalls wird der Schleifenkörper erneut ausgeführt.
until
Die until-Schleife, im Deutschen die Wiederhole-Bis-Schleife, ist das Gegenteil der While-Schleife. Sie führt den Schleifenkörper nur aus, wenn die Laufbedingung unwahr ist. Statt While wird das Schlüsselwort until zum Einleiten der Schleife verwendet. Ansonsten gelten für sie dieselben Regeln wie für die While-Schleife.
a = 1 until a >= 10 do a = a + 1 end a = a - 1 until a == 1 begin a = a - 1 end until a <= 1 print a #=> ergibt 0
for
Die For-Schleife ist in Ruby nur Syntaxzucker (das heißt, es ist eine verschönerte Schreibweise für etwas, das es schon gibt). Intern wird die For-Schleife als each-Iterator ausgeführt. Der einzige Unterschied zum direkten Ausführen der each Methode ist, dass lokale Variablen, die innerhalb der For-Schleife definiert wurden, auch außerhalb von ihr gültig sind.
Der Einsatzzweck für eine For-Schleife ist für gewöhnlich, einen Container mit Werten zu durchlaufen und einen Code für jeden Wert im Container auszuführen.
Syntaktisch ist eine For-Schleife folgendermaßen aufgebaut: Sie beginnt mit dem Schlüsselwort for. Danach folgt eine Liste an Parametern, die mit Kommata getrennt sind (und wie bei Iteratoren üblich) mit Klammern verschachtelt sein dürfen. In den meisten Fällen wird nur ein Parameter verlangt. Danach folgt das Schlüsselwort in und anschließend das Objekt, welches die each Methode ausführen soll. Danach darf optional ein do gesetzt werden. Daraufhin folgt der Schleifenkörper (wurde kein do gesetzt, muss vor dem Schleifenkörper ein Zeilenumbruch stehen). Die Schleife endet mit einem end Schlüsselwort.
array = ["Hallo", "schöne", "Welt"] for wort in array do print wort end hash = {1 => "eins", 2 => "zwei", 3 => "drei" } for zahl, wort in hash do print zahl.to_s + " heißt ausgeschrieben " + wort end range = 5..10 for zahl in range do print zahl end
Im Gegensatz zu den vorherigen Schleifentypen darf das For nicht hinter dem Schleifenkörper geschrieben werden.
Die For-Schleife ist semantisch äquivalent mit der each-Methode mit vorheriger Variablendeklaration:
array = [5, 4, 8, 2, 7] # die folgende For-Schleife for zahl in array do maximum = zahl if maximum.nil? or maximum < zahl end print maximum # ist semantisch äquivalent zu maximum = nil array.each do |zahl| maximum = zahl if maximum.nil? or maximum < zahl end print maximum # maximum muss also vor dem Beginn der each-Schleife deklariert werden # im Normalfall sollte man das sowieso immer tun
Wichtige wiederholende Iteratoren
Wie bereits erwähnt ist es in Ruby meistens besser Iteratormethoden statt Schleifen zu verwenden. Für Wiederholung von Code gibt es z.B. folgende Iteratormethoden:
loop
Wiederholt einen Code unendlich oft, bis die Schleife mit einer break Sprunganweisung beendet wird.
# Lose ziehen geld = 100 loop do geld = geld - 5 zufall = rand(10) if zufall <= 3 then print "Niete" elsif zufall <= 5 then print "Freilos" geld = geld + 5 else zufall <= 8 then print "Kleiner Gewinn" geld = geld + 15 else print "Jackpot!" geld = geld + 50 end if geld < 5 then break end end
times
Eine Methode der Klasse Integer. Sie wiederholt einen Code so oft, wie die Zahl des Objektes, welche die Methode ausführt. Als Parameter bekommt der Codeblock die Zahl der bereits durchgeführten Wiederholungen.
3.times do print "Hallo Welt" end #=> Hallo Welt #=> Hallo Welt #=> Hallo Welt 4.times do |i| print "Dies ist die " + i.to_s + "te Wiederholung" end #=> Dies ist die 0te Wiederholung #=> Dies ist die 1te Wiederholung #=> Dies ist die 2te Wiederholung #=> Dies ist die 3te Wiederholung
upto und downto
Ebenfalls Methoden der Klasse Integer. Sie zählen aufwärts / abwärts von sich selbst bis zum angegebenen Parameter und wiederholen ihren Codeblock, dem sie als Parameter den aktuellen Zähler übergeben.
3.upto(5) do |zahl| print zahl end #=> 3 #=> 4 #=> 5 6.downto(4) do |zahl| print zahl end #=> 6 #=> 5 #=> 4
step
Eine Methode der Klasse Numeric, die von dem ausführenden Objekt aufwärts zählt. Im Gegensatz zu upto funktioniert die Methode auch mit Kommazahlen und man kann angeben, in was für Schritten gezählt wird.
# zähle von 3 bis 12 in 3er Schritten 3.step(12, 3) do |zahl| print zahl end #=> 3 #=> 6 #=> 9 #=> 12 # zähle von 0.0 bis 1.0 in 0.2er Schritten 0.0.step(1.0, 0.2) do |zahl| print zahl end #=> 0.0 #=> 0.2 #=> 0.4 #=> 0.6 #=> 0.8 #=> 1.0
Die Methode ist auch für Range Objekte definiert und verlangt dann nur die Schrittweite als Parameter.
# zähle von 3 bis 12 in 3er Schritten (3..12).step(3) do |zahl| print zahl end #=> 3 #=> 6 #=> 9 #=> 12