Sie ist eine für die Programmierung unentbehrlich wichtige Struktur und (fast) so alt wie die Programmierung selbst: Die Bedingung. So gut wie jede Programmiersprache unterstützt Bedingungen, die mit dem Schlüsselwort if eingeleitet werden, in einer ähnlichen Syntax. Neben dieser bekannten Bedingungsabfrage gibt es noch einige andere, weniger bekannte, aber deshalb nicht weniger nützliche Arten den Wahrheitswert einer Bedingung abzufragen.
if
Die bekannteste Bedingung, deren Syntax in fast jeder Programmiersprache nahezu gleich ist. In Ruby kann man sowohl die Klammern um die Bedingung, als auch ein then hinter der Zeile (außer die Bedingung ist ein Einzeiler) weglassen. Wichtig dabei ist auch, dass Vergleiche in Ruby mit der Methode == und nicht mit der Zuweisung = durchgeführt werden. if not kann als unless geschrieben werden.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
a = true
if a == true
puts "a war true!"
end
#=> a war true!
# Wenn nur auf true überprüft wird, kann man das auch so schreiben:
if a
puts "a war true!"
end
#=> a war true!
#Jedes Objekt gilt in Ruby als true (außer false und nil)
a = 7
b = "T"
if a
puts "true"
end
if b
puts "true"
end
#=> true
#=> true
#Vorsicht!
if 0
puts "true"
end
#=> true
#Für if not a kann man auch unless benutzen:
a = false
unless a
puts "false"
end
#=> false
#--------------------------------------------------------------
a = true
if a then puts "a war true!" end
#=> a war true! |
Wie in vielen anderen Programmiersprachen, kennt Ruby auch die else-if und die else-Klausel, wobei else-if in Ruby zu elsif zusammengekürzt wird.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
a, b = true, false
#a = true; b = false
if b
puts "b war true!"
elsif a
puts "a war true!"
end
#=> a war true!
a, b, c = false, false, false
if a
puts "a war true!"
elsif b
puts "b war true!"
elsif c
puts "c war true!"
else
puts "Weder a noch b war true!"
end
#=> Weder a noch b war true! |
case
Für lange, geschachtelte Bedinungsabfragen, die sonst viele elsif-Teile benötigten, bietet sich das case-Konstrukt an. Es hat eine Besonderheit: Es führt die Vergleiche intern nicht mit der Methode ==, sondern mit der Methode === aus[1] (um Fragen vorzubeugen: Nein, eine Methode ==== gibt es nicht), das ist wichtig, wenn zum Beispiel Dinge verglichen werden, bei denen es eigentlich nicht um das Objekt selbst, sondern um etwas anderes geht. Die Variable, die man case mitgibt, kann gleichzeitig auf viele Werte überprüft werden:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
a = 3
case a
when 1
puts "a war 1"
when 2
puts "a war 2"
when 3
puts "a war 3"
else # <== Auch ein Case-Konstrukt kann eine else-Möglichkeit haben!
puts "a war weder 1 noch 2 noch 3. "
end
#=> a war 3
b = 2
case b
when 1 then puts "b war 1"
when 2 then puts "b war 2"
end
#=> b war 2
c = 1
case c
when 1;puts "c war 1"
when 2;puts "c war 2"
end
#=> c war 1
d = 0
case d
when 1 : puts "d war 1"
when 0 : puts "d war 0"
end
#=> d war 0
#Um den Unterschied zwischen == und === zu verdeutlichen:
a = 1..10 #Range mit den Werten von 1 bis einschließlich 10
b = 5
a == b #=> false
a === b #=> true, denn 5 ist in 1-10 enthalten.
#Ausformuliert heißt das:
if a == b
#Das hier wird nicht ausgeführt.
end
c = 1..4
case b # <== Aufpassen, b wird überprüft, nicht a!
when a #Man kann die Bedingung so formulieren: Wenn b in a enthalten ist...
#Das hier wird ausgeführt!
when c #Wenn b in c enthalten ist...
#Das hier wird nicht ausgeführt!
end |
?
Eine sehr kurze Möglichkeit bietet der Ternäroperator ?:. Ruby hat ihn aus C übernommen, seine Syntax ist:
Bedingung ? Wenn-true-mache-das-hier : Sonst-mache-das-hier
.
1
2
3
|
a = 1
a == 4 ? puts("a war 4") : puts("a war nicht 4.")
#=> a war nicht 4. |
Rückgabewerte
Was an Bedingungen überraschend sein kann, ist, dass sie Rückgabewerte haben, und zwar nicht nur true oder false. Eine Bedingungsabfrage gibt wie eine Methode immer den zuletzt "genannten" Wert zurück:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
a = 1
b = if a == 1
9
else
7
end
puts b #=> 9
#Ruby ignoriert beim Parsen des Codes den Whitespace, deswegen kann man sich das Case-Konstrukt
#getrost übersichtlich zurechtschieben.
c = case a
when 1
"a = 1"
when 2
"a = 2"
else
"a weder 1 noch 2"
end
puts c #=> a = 1
#Meistens benutzt man in solchen Fällen wohl den Ternäroperator:
d = a == 2 ? "a war 2" : "a war nicht 2"
puts d #=> a war nicht 2 |
Das kann durchaus zu seltsamen Konstruktionen führen:
1
2
3
4
5
6
7
8
9
10
11
|
a = 9
b = case a
when 8 then "a war 8" end
when 9 then "a war 9" end
end if a < 10
#Das heißt nichts anderes, als:
# 1. a wird der Wert 9 zugewiesen.
# 2. Es wird überprüft, ob a kleiner 10 ist,
# 3. Wenn ja, wird a genauer Überprüft und (Wenn nein, ist hier Ende und b kriegt nix)
# 4. b wird das Ergebnis dieser Überprüfung zugewiesen.
puts b #=> "a war 9" |
||and or not!&&
Bedingungen können mit den Schlüsselwörtern and, or und not oder mit ihren Kurzformen &&, || und ! verknüpft werden, wobei die Kurzformen eine höhere Priorität aufweisen:
1
2
3
4
5
6
7
8
9
10
11
12
|
a, b, c = true, 7, false
if a and b == 7 and !c
#Das hier wird ausgeführt
end
#In diesem Falle sind die Kurzformen gleich:
if a && b == 7 && !c
#Das hier wird auch ausgeführt
end
#Hier nicht:
if a && b == 7 and !c
#Entspricht nämlich:
if (a and b == 7) and (not c) |
Daneben gibt es noch &, | und ^, aber das sind keine Bedingungsoperatoren, sondern binäre:
1
2
3
|
1 & 0 #=> 0 (AND)
1 | 0 #=> 1 (OR)
1 ^ 0 #=> 1 (XOR) |
Fußnoten
-
case benutzt === aber nicht so, wie es in der Regel erwartet wird, sondern ruft die Methode === des zweiten Objekts anstatt des Ersten auf:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
a = 1
b = 2
case a
when b then puts "Gleich."
end
#Die Fallunterscheidung nutzt dabei diese Bedingungsabfrage:
b === a
#und nicht
a === b
#Als Methode geschrieben wird der Unterschied deutlich:
b.===(a)
#statt
a.===(b) |
Siehe auch