A falha é o fluxo de controle no Verse.
Ao contrário de outras linguagens de programação que usam os valores booleanos "true" e "false" para alterar o fluxo de um programa, a linguagem Verse usa [expressões]expressions-in-verse) que podem ser bem-sucedidas ou falhar. Essas expressões são chamadas de expressões falíveis e só podem ser executadas em um contexto de falha.
Usar a falha para o fluxo de controle significa que o trabalho não precisa ser duplicado e que você pode evitar erros sutis.
Por exemplo, em outras linguagens, você precisa verificar se um índice para uma matriz é válido antes de acessar o elemento da matriz nesse índice, o que é uma causa comum de erros em outras linguagens.
No Verse, a validação e o acesso são combinados para evitar isso.
Por exemplo:
if (Element := MyArray[Index]):
Log(Element)
Expressão falível
Uma expressão falível é uma expressão que pode ser bem-sucedida e produzir um valor ou falhar e não retornar nenhum valor. Exemplos de expressões falíveis incluem a indexação em uma matriz, pois um índice inválido falhará e o uso de operadores para comparar dois valores.
O código que você escreve não é falível por padrão. Por exemplo, para escrever uma função que pode falhar, você deve adicionar o especificador de efeito <decides> à definição da função. Atualmente, também é necessário adicionar <transacts> ao usar <decides>.
Consulte uma lista completa das expressões falíveis em: Expressões em Verse.
Contexto de falha
Um contexto de falha é um contexto em que é permitido executar expressões falíveis. O contexto define o que acontece se a expressão falhar. Qualquer falha dentro de um contexto de falha fará com que todo o contexto falhe.
Um contexto de falha permite que expressões aninhadas sejam expressões de falha, como argumentos de função ou expressões em uma expressão block.
Um aspecto útil dos contextos de falha no Verse é que eles são uma forma de execução especulativa, o que significa que você pode experimentar ações sem as confirmar. Quando uma expressão é bem-sucedida, os efeitos dela são confirmados, como a alteração no valor de uma variável. Se a expressão falhar, os efeitos dela serão revertidos, como se a expressão nunca tivesse acontecido.
Dessa forma, você pode executar uma série de ações que acumulam alterações, mas essas ações serão desfeitas se falharem em qualquer lugar.
Para que isso funcione, todas as funções chamadas no contexto de falha devem ter o especificador de efeito <transacts> e o compilador reclamará se não tiverem.
Funções definidas pelo usuário não têm o efeito transacts por padrão. Um especificar <transacts> explícito devem ser adicionado a suas definições. Algumas funções nativas também não têm o efeito transacts e não podem ser chamadas em contextos de falha.
Um exemplo de uma função nativa sem transacts poderia ser um audio_component com um método BeginSound(). Se o som for iniciado, mesmo que tenha sido interrompido, ele poderia ter sido notado.
A lista a seguir inclui todos os contextos de falha no Verse:
-
A condição em expressões
if. ~~~(verse) if (test-arg-block) { … } -
As expressões de iteração e as expressões de filtro em expressões `for`. Observe que `for` é especial porque cria um contexto de falha para cada iteração. Se as iterações estiverem [aninhadas](verse-glossary#nested), os contextos de falha também ficarão aninhados. Quando uma expressão falha, o contexto de falha mais interno é anulado, e a iteração delimitadora, se houver, continuará com a próxima iteração. ~~~(verse) for (Item : Collection, test-arg-block) { … } ~~~
-
O corpo de uma função ou método que tem o especificador de efeito `<decides>`. ~~~(verse) IsEqual()<decides><transacts> : void = { … }
-
O operando para o operador
not.not expression ~~~ -
O operando esquerdo para `or`. ~~~(verse) expression1 or expression2
-
Inicializando uma variável que tem o tipo
option.option{expression}