Die Programmiersprache Ruby

Blog| Forum| Wiki  

Be aware of the possibility of an infinite loop.
An wie vielen Stellen erhält man eine solche oder eine ähnliche Warnung? Endlosschleifen lassen sich doch viel einfacher als aus Versehen generieren:

1
2
3
loop do
  #Ich werde niemals enden...
end

Nun gut, so weit also zur Endlosschleife, die man nicht mit Konstrukten wie while true generieren muss. Ruby kennt einige Arten von Schleifen:

Inhaltsverzeichnis

while

Syntax

while [expr] [do]
  #Code...
end

Beschreibung

Die Schleife läuft, solange ein Ausdruck (expr) true ergibt. Das Schlüsselwort do ist optional, alternativ kann man auch die geschweifte Klammer ({}) verwenden (Priorität beachten!).

1
2
3
4
a = 0
while a < 9
  a += 1
end

until

Syntax

until [expr] [do]
  #Code...
end

Beschreibung

Diese Schleife ist das Gegenteil von while. Sie läuft, solange ein Ausdruck false ist, bzw. bis er true ergibt. Auch hier ist do optional.

1
2
3
4
a = 0
until a >= 9
  a += 1
end

Anhängsel

Sowohl while als auch until lassen sich als Ausdrucksanhängsel benutzen:

1
2
3
4
a = 0
a += 1 while a < 9
a = 0
a += 1 until a >= 9

for

Syntax

for [element] in [objekt] [do]
  #Code...
end

Beschreibung

Sofern ein Objekt ein Enumerable ist, geht das iterierende for dieses Objekt Stück für Stück durch. In der Regel entspricht dies allerdings einem Aufruf der Methode each eines Objekts. do ist optional.

1
2
3
4
5
6
7
8
ary = [1, 2, 3]
ary.each do |element|
  puts element
end
#Ist das gleiche wie
for element in ary do
  puts element
end

Gültigkeitsbereiche

Die Schleifen while, until und for sind zugleich eine Besonderheit in Ruby: Sie besitzen keinen eigenen Gültigkeitsbereich. Das ist sehr ungewöhnlich, da für gewöhnlich jeder Codeblock ein Bereich für sich ist, aber Schleifen handhaben das anders.

1
2
3
4
5
6
x = 0
while x < 2
  y = "Lokal?"
  x += 1
end
puts y #=> Lokal?

Andere Schleifen

Zusätzlich zu diesen Grundschleifen (die bis auf for eigentlich nur selten benutzt werden) bieten viele Objekte eigene Schleifen an, wie zum Beispiel String each_byte. Die populärsten und vermutlich meist benutzten bietet die Klasse Fixnum, es sind die Methoden times, downto und upto.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
3.times{|zahl| puts zahl}
#=> 0
#=> 1
#=> 2

0.upto(2){|zahl| puts zahl}
#=> 0
#=> 1
#=> 2

2.downto(0) do |zahl|
  puts zahl
end
#=> 2
#=> 1
#=> 0

Rekursion

Neben der herkömmlichen Art, Schleifen zu genererieren, besteht die Möglichkeit der Rekursion. Dabei ruft sich eine Methode innerhalb ihres Codes selbst auf:

1
2
3
4
5
def potenzieren(basis, exponent = 2)
  return exponent == 0 ? 1 : basis * potenzieren(basis, exponent - 1)
end
puts "3 hoch 3 ergibt #{potenzieren(3, 3)}. "
#=> 3 hoch 3 ergibt 27.


Stoppen und anderes

Man sollte wissen, wie jede Schleife gestoppt werden kann. Wenig bekannt dabei ist, dass man den folgenden Schlüsselwörtern einen Rückgabewert mitgeben kann, z.B. break(3).

break

Das Schlüsselwort break bricht eine Schleife oder einen Iterator ohne zu fragen ab.

1
2
3
4
5
6
a = 1
loop do
  a -= 1
  break if a < -5
end
#a ist jetzt -6.

redo

retry hat, wie oft fälschlich angenommen wird, nichts mit Schleifen zu tun, siehe dazu Exception. Was gemeint ist, ist in der Regel redo, was bewirkt, dass der aktuelle Schleifendurchlauf vom Anfang ab noch einmal wiederholt wird.

1
2
3
4
5
6
a = 0
3.times do
  a += 1
  redo if a == 2
end
#a ist jetzt 4.

next

Daneben gibt es noch next, der aktuelle Durchlauf wird an dieser Stelle abgebrochen und der nächste gestartet.

1
2
3
4
5
3.times do
  next if a == 2
  a += 1
end
#a ist jetzt 2.

Siehe auch