L'échec est le flux de contrôle dans Verse.
Contrairement à d'autres langages de programmation qui utilisent les valeurs booléennes true et false pour modifier le flux d'un programme, Verse utilise des expressions qui peuvent soit réussir, soit échouer. Ces expressions sont appelées expressions faillibles et ne peuvent être exécutées que dans un [contexte d'échec] (verse-glossary#failure-context).
L'utilisation de l'échec pour le flux de contrôle signifie qu'il n'est pas nécessaire de dupliquer le travail, et que vous pouvez éviter des erreurs subtiles.
Par exemple, dans d'autres langages, vous devez vérifier qu'un index pour une matrice est valide avant d'accéder à l'élément de matrice à cet index, ce qui est une cause fréquente d'erreurs dans d'autres langages.
Dans Verse, la validation et l'accès sont combinés pour éviter cela.
Par exemple :
if (Element := MyArray[Index]):
Log(Element)
Expression faillible
Une expression faillible est une expression qui peut soit réussir et produire une valeur, soit échouer et ne renvoyer aucune valeur. Parmi les exemples d'expressions faillibles figurent l'indexation dans une matrice, car un index invalide échouera, et l'utilisation d'[opérateurs] (verse-glossary#operator), comme la comparaison de deux valeurs.
Le code que vous écrivez n'est pas faillible par défaut. Par exemple, pour écrire une fonction qui peut échouer, vous devez ajouter le spécificateur d'effet <decides> à la définition de la fonction. Actuellement, il est également nécessaire d'ajouter <transacts> lorsque <decides> est utilisé.
Pour une liste complète des expressions faillibles, consultez la liste des expressions dans Verse.
Contexte d'échec
Un contexte d'échec est un contexte où il est permis d'exécuter des expressions faillibles. Le contexte définit ce qui se passe si l'expression échoue. Tout échec au sein d'un contexte d'échec entraînera l'échec de l'ensemble du contexte.
Un contexte d'échec permet aux expressions imbriquées d'être des expressions d'échec, par exemple des arguments de fonction ou des expressions dans une expression block.
Un aspect utile des contextes d'échec dans Verse est qu'ils constituent une forme d'exécution spéculative, ce qui signifie que vous pouvez essayer des actions sans les valider. Lorsqu'une expression réussit, les effets de l'expression sont validés, comme le changement de la valeur d'une variable. Si l'expression échoue, les effets de l'expression sont [annulés] (verse-glossary#rollback), comme si l'expression n'avait jamais eu lieu.
De cette façon, vous pouvez exécuter une série d'actions qui provoquent des changements, mais ces actions seront annulées si elles échouent quelque part.
Pour que cela fonctionne, toutes les fonctions appelées dans le contexte d'échec doivent avoir le spécificateur d'effet <transacts>, et le compilateur se plaindra si ce n'est pas le cas.
Les fonctions définies par l'utilisateur n'ont pas l'effet transacts par défaut. Un spécificateur <transacts> explicite doit être ajouté à leurs définitions. Certaines fonctions natives n'ont pas non plus l'effet transacts et ne peuvent pas être appelées dans des contextes d'échec.
Un exemple de fonction native sans transacts pourrait être un composant_audio avec une méthode BeginSound(). Si le son est lancé, il peut être remarqué, même en cas d'arrêt.
La liste suivante énumère tous les contextes d'échec dans Verse :
-
La condition dans les expressions 'if'.
if (test-arg-block) { … } -
Les expressions d'itération et les expressions de filtre dans les expressions
for. Notez queforest spécial dans la mesure où il crée un contexte d'échec pour chaque itération. Si les itérations sont imbriquées, alors les contextes d'échec seront également imbriqués. Lorsqu'une expression échoue, le contexte d'échec le plus interne est abandonné, et l'itération qui l'enferme, le cas échéant, continue avec l'itération suivante.for (Item : Collection, test-arg-block) { … } -
Le corps d'une fonction ou d'une méthode qui a le spécificateur d'effet
<decides>.IsEqual()<decides><transacts> : void = { … } -
L'opérande pour l'opérateur
not.not expression -
L'opérande de gauche pour
or.expression1 or expression2 -
Initialisation d'une variable disposant du type
option.option{expression}