Con la expresión de condición if, puedes tomar decisiones que cambian el flujo del programa. Al igual que en otros lenguajes de programación, la expresión de condición if de Verse admite la ejecución condicional, pero en Verse, las condiciones utilizan el éxito y el fracaso para impulsar la decisión.
Por ejemplo, puedes escribir un código que defina la altura de caída que puede tener un jugador antes de recibir daño.
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()En este ejemplo, si PlayerFallHeight es mayor de tres metros, entonces la condición tiene éxito y se ejecuta DealDamage() antes de que se restablezca la altura de caída del jugador. De lo contrario, la condición falla, por lo que el jugador no recibe ningún daño, pero la altura de caída del jugador se restablece.
if
El ejemplo de la altura de la caída del jugador utilizaría la siguiente sintaxis:
expression0
if (test-arg-block):
expression1
expression2Después de ejecutar expression0, el programa Verse entra en el bloque `if`. Si test-arg-block tiene éxito, entonces el programa Verse ejecuta expression1, que puede ser una expresión o un bloque de expresiones. En caso contrario, si test-arg-block falla, el programa Verse omite expression1 y solo ejecuta expression2.
Diagrama de flujo de la lógica del bloque `if`.
if... else
También puedes especificar una expresión que se ejecute cuando la expresión if falla.
Por ejemplo, el jugador debería ganar una habilidad de doble salto si cae menos de tres metros y si su medidor de salto está al 100 %. Pero si caen más de tres metros o su medidor de salto no está al 100 %, los brazos del personaje se agitarán para hacer saber al jugador que no puede realizar un doble salto.
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!
En este ejemplo, la condición de if evalúa si PlayerFallHeight es menor de tres metros y si JumpMeter es igual al 100 %. Si la condición tiene éxito, ActivateDoubleJump() y ZeroPlayerFallHeight() se ejecutan antes de SetDoubleJumpCooldown().
Si la condición if falla, la expresión ActivateFlapArmsAnimation() que sigue a else se ejecuta antes de SetDoubleJumpCooldown().
Sintácticamente, el ejemplo if-else debe parecerse a esto:
expression0
if (test-arg-block):
expression1
else:
expression2
expression3Diagrama de flujo de la lógica del bloque `if-else`.
if... if else... else
Si un jugador tiene un 100 % de escudos cuando cae más de tres metros, debería recibir el máximo daño, pero seguir sobreviviendo. Y modifiquemos la regla que otorga a los jugadores la habilidad de doble salto, de tal forma que los jugadores sólo obtengan el doble salto si caen menos de tres metros y si su medidor de salto es superior al 75 %.
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
Sintácticamente, el ejemplo `if-else if-else` debe parecerse a esto:
expression0
if (test-arg-block0):
expression1
else if (test-arg-block1):
expression2
else:
expression3
expression4Diagrama de flujo de la lógica del bloque `if-else if-else`.
if... then
Puedes escribir cualquiera de las condiciones if de los ejemplos anteriores en varias líneas sin cambiar su funcionamiento:
expression0
if:
test-arg-block
then:
expression1
expression2El bloque de código test-arg-block puede contener una o más líneas de condiciones, pero todas ellas deben tener éxito para ejecutar expression1 antes de expression2, de lo contrario solo se ejecutará expression2.
El ejemplo de la sección `if... else` reescrito en este formato tiene el siguiente aspecto:
var PlayerFallHeight : float = CalculatePlayerFallHeight()
if:
PlayerFallHeight < 3.0
JumpMeter = 100
then:
# Perform a double jump.
ActivateDoubleJump()
# Reset the player’s fall height.
ZeroPlayerFallHeight()
Expresión de única línea
Puedes escribir un if else como una expresión de una única línea, similar a los operadores ternarios en otros lenguajes de programación. Por ejemplo, si quieres asignar un valor máximo o mínimo de Recharge basado en ShieldLevel de un jugador, puedes escribir el siguiente código de Verse:
Recharge : int = if(ShieldLevel < 50) then GetMaxRecharge() else GetMinRecharge()Requisitos de predicado
El predicado de if, que es la expresión entre paréntesis (), se diferencia de otros lenguajes de programación en que no se espera que devuelva un booleano (llamado logic en Verse). En su lugar, se espera que el predicado tenga el efecto decides (nótese que, aunque la subtipificación normalmente permite un subconjunto de efectos en lugares que permiten un conjunto de efectos, `if` requiere que el efecto global del predicado incluya decides). El efecto se elimina del ámbito circundante. Es decir, el efecto decides de todas las operaciones del predicado if es consumido por la construcción if. Por ejemplo, en el código siguiente, Main no tiene el efecto decides, aunque invoca a Foo, que sí lo tiene.
Foo()<transacts><decides> : void = {}
Bar() : void = {}
Main() : void =
if (Foo[]):
Bar()Esto se debe a que, en lugar de utilizar una entrada logic a if para elegir qué derivación se toma, el éxito de las operaciones contenidas en el predicado de if se utiliza para decidir la derivación apropiada (la derivación then si todas las operaciones tienen éxito, la derivación else, si está presente, si alguna operación falla). Ten en cuenta que esto significa que se pueden utilizar operaciones arbitrarias en el predicado if, incluyendo la introducción de constantes. Por ejemplo:
Main(X : int) : void =
Y = array{1, 2, 3}
if:
Z0 := Y[X]
Z1 := Y[X + 1]
then:
Use(Z0)
Use(Z1)Dicho de otro modo, el ámbito de la derivación then incluye cualquier nombre introducido en el predicado if.
Comportamiento transaccional
Otra desviación de if con respecto a otros lenguajes de programación es el comportamiento transaccional del predicado a if. El predicado a if no debe tener el efecto no_rollback (utilizado implícitamente por todas las funciones que no especifican explícitamente transacts, varies o computes). Esto se debe a que en el caso de que el predicado falle, todas las operaciones realizadas durante la ejecución del predicado (excepto cualquier operación que afecte a los recursos fuera del tiempo de ejecución, como la E/S de archivos o la escritura en la consola) se deshacen antes de la ejecución de la derivación else. Por ejemplo:
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)
La función Foo(-1) devolverá 0, mientras que Foo(1) devolverá 1. Esto se debe a que, aunque la llamada a Incr ocurre antes de la prueba de X > 0, la mutación de Y que provoca se deshace antes de la ejecución de la derivación else. Ten en cuenta que Incr tuvo que especificar manualmente el efecto transacts. Por defecto, no se proporciona el comportamiento transaccional, indicado por el efecto implícito no_rollback, pero se puede añadir especificando el efecto transacts manualmente (anulando el efecto implícito no_rollback).