El fallo es el flujo de control en Verse.
A diferencia de otros lenguajes de programación que utilizan los valores booleanos true y false para cambiar el flujo de un programa, Verse utiliza expresiones que pueden tener éxito o fallar. Estas expresiones se conocen como expresiones falibles, y solo pueden ejecutarse en un contexto de fallo.
El uso de fallos para el flujo de control significa que el trabajo no tiene que duplicarse, y que puedes evitar errores sutiles.
Por ejemplo, en otros idiomas, hay que comprobar que el índice para la matriz es válido antes de acceder al elemento de la matriz en ese índice, lo cual es una causa común de errores en otros idiomas.
En Verse, la validación y el acceso se combinan para evitarlo.
Por ejemplo:
if (Element := MyArray[Index]):
Log(Element)
Expresión falible
Una expresión falible es una expresión que puede tener éxito y producir un valor, o fallar y no devolver ningún valor. Ejemplos de expresiones falibles incluyen la indexación en una matriz porque un índice no válido fallará, y el uso de operadores como la comparación de dos valores.
El código que escribes no es falible por defecto. Por ejemplo, para escribir una función que pueda fallar, debes añadir el efecto especificador <decides> a la definición de la función. Actualmente también es necesario añadir <transacts> cuando se utiliza <decides>.
Para obtener una lista completa de las expresiones falibles, consulta la lista de Expresiones en Verse.
Contexto de fallo
Un contexto de fallo es un contexto en el que se permite ejecutar expresiones falibles. El contexto define lo que ocurre si la expresión falla. Cualquier error en un contexto de fallo hará que todo el contexto falle.
Un contexto de fallo permite que las expresiones anidadas sean expresiones de fallo, como expresiones o argumentos de función en una expresión de bloque.
Un aspecto útil de los contextos de fallo en Verse es que constituyen una forma de ejecución especulativa, lo que significa que puedes probar acciones sin confirmar. Cuando una expresión tiene éxito, los efectos de la expresión se confirman, como cambiar el valor de una variable. Si la expresión falla, los efectos de la expresión se revierten, como si la expresión nunca hubiera ocurrido.
De esta manera, puedes ejecutar una serie de acciones que acumulen cambios, pero esas acciones se desharán si fallan en algún lugar.
Para que esto tenga lugar, todas las funciones llamadas en el contexto de fallo deben tener el especificador de efecto <transacts>, ya que si no lo tienen, el compilador protestará.
Las funciones definidas por el usuario no tienen el efecto transacts predeterminado. Hay que añadir un especificador explícito <transacts> a sus definiciones. Algunas funciones nativas tampoco disponen del efecto transacts y no pueden ser llamadas en contextos de fallo.
Un ejemplo de función nativa sin transacts podría ser un audio_component con un método BeginSound(). Si el sonido se inicia, aunque se detenga podría haberse notado.
La siguiente lista incluye todos los contextos de fallo en Verse:
-
La condición en expresiones
if.if (test-arg-block) { … } -
Las expresiones de iteración y de filtro en las expresiones
for. Ten en cuenta quefores especial porque crea un contexto de fallo para cada iteración. Si las iteraciones están anidadas, entonces los contextos de fallo también estarán anidados. Cuando una expresión falla, el contexto de fallo más interno se aborta, y la iteración envolvente, si la hay, continúa con la siguiente iteración.for (Item : Collection, test-arg-block) { … } -
El cuerpo de una función o método que tiene el especificador de efecto
<decides>.IsEqual()<decides><transacts> : void = { … } -
El operando del operador
not.not expression -
El operando de la izquierda de
or.expression1 or expression2 -
Inicializando una variable que tiene el tipo
option.option{expression}