Mit dem if-Ausdruck kannst du Entscheidungen treffen, die den flow des Programms verändern. Wie in anderen Programmiersprachen unterstützt der if-Ausdruck in Verse die bedingte Ausführung, aber in Verse verwenden die Bedingungen Erfolg und Fehlschlag, um die Entscheidung zu treffen.
Du kannst zum Beispiel einen Code schreiben, der die Fallhöhe festlegt, die ein Spieler erreichen kann, bevor er Schaden nimmt.
var PlayerFallHeight : float = CalculatePlayerFallHeight()
# Players take damage if they fall more than 3 meters
if (PlayerFallHeight > 3.0):
DealDamage()
# Reset the player’s fall height
ZeroPlayerFallHeight()Wenn in diesem Beispiel PlayerFallHeight größer als drei Meter ist, ist die Bedingung erfüllt und DealDamage() wird ausgeführt, bevor die Fallhöhe des Spielers zurückgesetzt wird. Andernfalls schlägt die Bedingung fehl, sodass der Spieler keinen Schaden erleidet, aber die Fallhöhe des Spielers zurückgesetzt wird.
if
Das Beispiel der Fallhöhe des Spielers würde die folgende syntax verwenden:
expression0
if (test-arg-block):
expression1
expression2Nach der Ausführung von expression0 geht das Verse-Programm in den if-Block. Wenn der test-arg-block erfolgreich ist, führt das Verse-Programm expression1 aus, der ein Ausdruck oder ein Block von Ausdrücken sein kann. Andernfalls, wenn der test-arg-block fehlschlägt, überspringt das Verse-Programm expression1 und führt nur expression2 aus.
Ablaufdiagramm für die if-Block-Logik.
if ... else
Du kannst auch einen Ausdruck angeben, der ausgeführt werden soll, wenn der if-Ausdruck fehlschlägt.
Beispielsweise sollte der Spieler eine Doppelsprungfähigkeit erlangen, wenn er weniger als drei Meter fällt und sein Sprungzähler auf 100 Prozent steht. Aber wenn er mehr als drei Meter fällt oder sein Sprungzähler nicht 100 Prozent erreicht, flattern die Arme der Spielfigur, um den Spieler wissen zu lassen, dass er nicht doppelt springen kann.
var PlayerFallHeight : float = CalculatePlayerFallHeight()
if (PlayerFallHeight < 3.0 and JumpMeter = 100):
# Perform a double jump.
ActivateDoubleJump()
# Reset the player’s fall height.
ZeroPlayerFallHeight()
else:
# Flap the character’s arms to tell the player they
# cannot double jump right now!
In diesem Beispiel wertet die Bedingung von if aus, ob PlayerFallHeight kleiner als drei Meter und JumpMeter gleich 100 Prozent ist. Wenn die Bedingung erfüllt ist, werden ActivateDoubleJump() und ZeroPlayerFallHeight() vor SetDoubleJumpCooldown() ausgeführt.
Wenn die if-Bedingung nicht erfüllt ist, wird der Ausdruck ActivateFlapArmsAnimation() nach else vor SetDoubleJumpCooldown() ausgeführt.
Syntaktisch sieht das if-else-Beispiel so aus:
expression0
if (test-arg-block):
expression1
else:
expression2
expression3Ablaufdiagramm für die if-else-block-Logik.
if ... else if ... else
Wenn ein Spieler 100 Prozent Schilde hat und mehr als drei Meter fällt, sollte er maximalen Schaden nehmen, aber trotzdem überleben. Und lass uns die Regel ändern, die Spielern die Fähigkeit des Doppelsprungs gibt, so dass Spieler nur dann einen Doppelsprung erzielen, wenn sie weniger als drei Meter fallen und ihr Sprungzähler mehr als 75 Prozent beträgt.
var PlayerFallHeight : float = CalculatePlayerFallHeight()
if (PlayerFallHeight > 3.0 and shields = 100):
DealMaximalDamage()
return false
else if (PlayerFallHeight < 3.0 and JumpMeter > 75):
ActivateDoubleJump()
return false
else:
return true
Syntaktisch sieht das if-else if-else-Beispiel so aus:
expression0
if (test-arg-block0):
expression1
else if (test-arg-block1):
expression2
else:
expression3
expression4Ablaufdiagramm für die if-else if-else-Block-Logik.
if ... then
Du kannst jede der Bedingungen if in den vorherigen Beispielen in mehrere Zeilen schreiben, ohne ihre Funktionsweise zu ändern:
expression0
if:
test-arg-block
then:
expression1
expression2Der Codeblock test-arg-block kann eine oder mehrere Zeilen mit Bedingungen enthalten, aber sie müssen alle erfolgreich sein, um expression1 vor expression2 auszuführen, andernfalls wird nur expression2 ausgeführt.
Das Beispiel aus dem Abschnitt if ... else, das in diesem Format geschrieben wurde, sieht wie folgt aus:
var PlayerFallHeight : float = CalculatePlayerFallHeight()
if:
PlayerFallHeight < 3.0
JumpMeter = 100
then:
# Perform a double jump.
ActivateDoubleJump()
# Reset the player’s fall height.
ZeroPlayerFallHeight()
Einzeiliger Ausdruck
Du kannst ein if else als einzeiligen Ausdruck verfassen, ähnlich wie ternäre Operatoren in anderen Programmiersprachen. Wenn du zum Beispiel einen maximalen oder minimalen Recharge-Wert basierend auf dem ShieldLevel eines Spielers zuweisen möchtest, kannst du den folgenden Verse-Code schreiben:
Recharge : int = if(ShieldLevel < 50) then GetMaxRecharge() else GetMinRecharge()Prädikatanforderungen
Das predicate von if, d. h. der Ausdruck zwischen den Klammern (), unterscheidet sich von anderen Programmiersprachen dadurch, dass nicht erwartet wird das ein boolesche Wert zurückgeben wird (in Verse logic genannt). Stattdessen wird erwartet, dass das Prädikat den Effekt decides hat (beachte, dass die Subtypisierung normalerweise eine Teilmenge von Effekten an Stellen zulässt, die einen Satz von Effekten zulassen, das aber der Gesamteffekt des Prädikats decides enthalten muss). Der Effekt wird aus dem umgebenden Bereich entfernt. Das heißt, der Effekt decides von allen Operationen im Prädikat if wird vom Konstrukt if verbraucht. Zum Beispiel hat Main im folgenden Code nicht den decides-Effekt, obwohl es Foo aufruft, das dies tut.
Foo()<transacts><decides> : void = {}
Bar() : void = {}
Main() : void =
if (Foo[]):
Bar()Das liegt daran, dass nicht eine Eingabe logic für if verwendet wird, um zu entscheiden, welche Verzweigung genommen wird, sondern der Erfolg der im Prädikat des if enthaltenen Operationen verwendet wird, um die passende Verzweigung zu wählen – die then-Verzweigung, wenn alle Operationen erfolgreich sind, die else-Verzweigung (falls vorhanden), wenn einige Operationen fehlschlagen. Beachte, dass dies bedeutet, dass im Prädikat if beliebige Operationen verwendet werden können, einschließlich der Einführung von Konstanten. Beispiel:
Main(X : int) : void =
Y = array{1, 2, 3}
if:
Z0 := Y[X]
Z1 := Y[X + 1]
then:
Use(Z0)
Use(Z1)Anders ausgedrückt, der Gültigkeitsbereich der Verzweigung then umfasst alle Namen, die im Prädikat if eingeführt werden.
Transaktionsverhalten
Eine weitere Abweichung von if in Bezug auf andere Programmiersprachen ist das transaktionale Verhalten des Prädikats zu if. Das Prädikat für if darf nicht den Effekt no_rollback haben (wird implizit von allen Funktionen verwendet, die nicht explizit transacts, varies oder computes angeben). Dies liegt daran, dass für den Fall, dass das Prädikat fehlschlägt, alle während der Ausführung des Prädikats durchgeführten Operationen (mit Ausnahme von Operationen, die sich auf Ressourcen außerhalb der Laufzeit auswirken, wie z. B. Datei-E/A oder das Schreiben auf die Konsole), vor der Ausführung der Verzweigung else rückgängig gemacht werden. Beispiel:
int_ref := class:
var Contents : int
Incr(X : int_ref)<transacts> : void =
set X.Contents += 1
Foo(X : int) : int =
Y := int_ref{Contents := 0}
if:
Incr(Y)
Die Funktion Foo(-1) gibt 0 zurück, während Foo(1) 1 zurückgibt. Dies liegt daran, dass der Aufruf von Incr zwar vor dem Test von X > 0 erfolgt, die dadurch verursachte Mutation von Y aber vor der Ausführung der Verzweigung else erfolgt. Beachte, dass Incr den Effekt transacts manuell angeben musste. Standardmäßig ist kein Transaktionsverhalten vorgesehen, was durch den impliziten Effekt no_rollback angezeigt wird, aber es kann hinzugefügt werden, indem der Effekt transacts manuell angegeben wird (wodurch der implizite Effekt no_rollback außer Kraft gesetzt wird).