if, unless & Schleifen
Kontrollfluss in Ruby - mit Statement-Modifiers, unless, until und den vielen Iterator-Methoden auf Zahlen und Sammlungen.
Inhaltsverzeichnis
Kontrollstrukturen in Ruby
Ruby hat die klassischen if und Schleifen - plus ein paar Besonderheiten, die dir in anderen Sprachen fehlen werden.
if / elsif / else
alter = 18
if alter >= 18
puts "Volljaehrig"
elsif alter >= 16
puts "Fast volljaehrig"
else
puts "Zu jung"
end
Merke:
- Kein
then/{noetig - einfach Zeilenumbruch - Abschluss mit
end elsif, nichtelse if
Statement-Modifier
Ein Ruby-Idiom: if hinter der Anweisung:
puts "Volljaehrig" if alter >= 18
Das ist bei einer Zeile lesbarer als ein vollstaendiges if/end.
if als Ausdruck
text = if alter >= 18 then "volljaehrig" else "minderjaehrig" end
# Oder mehrzeilig
text = if alter >= 18
"volljaehrig"
else
"minderjaehrig"
end
Der Ternaer-Operator geht auch:
text = alter >= 18 ? "volljaehrig" : "minderjaehrig"
unless - die Umkehrung
unless ist if not:
unless aktiv
puts "Inaktiv"
end
# Klassisch:
puts "Inaktiv" if !aktiv
Als Statement-Modifier sehr lesbar:
return unless valid?
Lies: โGib zurueck, ausser es ist valid.โ
Vermeide unless mit else - das verwirrt:
# Schlecht
unless alter >= 18
puts "zu jung"
else
puts "volljaehrig"
end
# Besser: if benutzen
case / when - das Ruby-Switch
punkte = 85
note = case punkte
when 90..100 then "A"
when 80..89 then "B"
when 70..79 then "C"
when 0..69 then "F"
else "ungueltig"
end
when-Bedingungen koennen Bereiche, Werte, Klassen, Regexe sein- Case-Ausdruck liefert einen Wert
thenist fuer einzeilige Zweige
case mit Typen
def beschreibe(wert)
case wert
when Integer then "Zahl: #{wert}"
when String then "String: #{wert.length} Zeichen"
when nil then "nil"
when true, false then "Boolean"
else "sonst"
end
end
Pattern Matching (Ruby 3+)
Ruby hat seit 3.0 echtes Pattern Matching:
case data
in { name: String => name, alter: Integer => alter }
puts "#{name}, #{alter}"
in [first, *rest]
puts "Array mit #{rest.length + 1} Elementen"
in nil
puts "nichts da"
end
Hierdurch wird Ruby in Sachen Ausdrucksstarke mit funktionalen Sprachen wie Rust vergleichbar.
Schleifen
while und until
n = 10
while n > 0
puts n
n -= 1
end
# Inverses Gegenstueck
until n == 0
puts n
n -= 1
end
Als Statement-Modifier:
puts n while (n -= 1) > 0
loop - Endlosschleife
loop do
print "> "
eingabe = gets.chomp
break if eingabe == "quit"
puts "Du sagtest: #{eingabe}"
end
for - selten genutzt
for i in 1..5
puts i
end
Stattdessen meistens:
(1..5).each { |i| puts i }
Der Vorteil: each schafft einen eigenen Scope, for nicht.
Iteratoren - der Ruby-Weg
Ruby-Entwickler lieben Iteratoren statt klassische Schleifen:
5.times do |i|
puts "Iteration #{i}" # 0, 1, 2, 3, 4
end
3.upto(7) { |n| puts n } # 3 4 5 6 7
10.downto(5) { |n| puts n } # 10 9 8 7 6
(1..5).each { |n| puts n }
each auf Sammlungen
namen = ["Max", "Anna", "Leo"]
namen.each do |name|
puts "Hallo, #{name}!"
end
namen.each_with_index do |name, i|
puts "#{i}: #{name}"
end
map, select, reject, reduce
zahlen = [1, 2, 3, 4, 5]
zahlen.map { |n| n * 2 } # [2, 4, 6, 8, 10]
zahlen.select { |n| n.even? } # [2, 4]
zahlen.reject { |n| n.even? } # [1, 3, 5]
zahlen.reduce(:+) # 15 (Summe)
zahlen.sum # 15 (Kurzform)
zahlen.min # 1
zahlen.max # 5
zahlen.sort # [1, 2, 3, 4, 5]
zahlen.reverse # [5, 4, 3, 2, 1]
zahlen.include?(3) # true
Ketten
zahlen
.select { |n| n > 1 }
.map { |n| n * 10 }
.sum
# => 140
break, next, redo
[1, 2, 3, 4, 5].each do |n|
next if n.even? # ueberspringen (continue)
break if n > 3 # abbrechen
puts n # 1, 3
end
break- Schleife verlassennext- zur naechsten Iteration (wiecontinue)redo- aktuelle Iteration neu starten (selten)
break mit Wert
ergebnis = [1, 2, 3].each do |n|
break "Gefunden: #{n}" if n == 2
end
# "Gefunden: 2"
Exceptions
begin
zahl = Integer(eingabe)
puts zahl
rescue ArgumentError => e
puts "Keine gueltige Zahl: #{e.message}"
rescue => e
puts "Anderer Fehler: #{e.message}"
ensure
puts "Immer ausgefuehrt"
end
Ruby-Style: begin / rescue / ensure / end.
Im Methodenrumpf geht das kompakter:
def sicher_konvertieren(text)
Integer(text)
rescue ArgumentError
0
end
Praktisches Beispiel
def kategorisiere(alter)
case alter
when ..0 then "ungueltig"
when 1..17 then "Kind"
when 18..64 then "Erwachsen"
else "Senior"
end
end
print "Alter: "
alter_text = gets.chomp
alter = Integer(alter_text) rescue nil
if alter.nil?
puts "Bitte eine Zahl eingeben."
exit 1
end
puts "#{alter} Jahre: #{kategorisiere(alter)}"
Zusammenfassung
if/elsif/else/end- klassisch, plus Statement-Modifierx if bedingungunlessals โif notโ-Gegenstueckcase/whenkann Ranges, Typen und Werte matchen; ab Ruby 3 mit Pattern Matching- Iteratoren wie
times,each,map,selectsind idiomatisch - klassische for-Schleifen selten next,break,redofuer Schleifen-Kontrollebegin/rescuefuer Exceptions
Im naechsten Kapitel: Methoden mit Keyword-Args, Default-Werten und Rubys Block-Magie.