L'errore è il flusso di controllo in Verse.
A differenza di altri linguaggi di programmazione che utilizzano i valori booleani true e false per modificare il flusso di un programma, Verse utilizza espressioni che possono riuscire o non riuscire. Queste espressioni sono chiamate espressioni fallibili e si possono eseguire solo in un contesto di errore.
Usare l'errore per il flusso di controllo significa che il lavoro non deve essere duplicato e che si possono evitare errori sottili.
Ad esempio, in altre lingue, è necessario verificare che un indice per un array sia valido prima di accedere all'oggetto dell'array a quell'indice, il che è una causa comune di errori in altre lingue.
In Verse, la convalida e l'accesso sono combinati per evitare questo problema.
Ad esempio:
if (Element := MyArray[Index]):
Log(Element)
Espressione fallibile
Si dice fallibile un'espressione che può avere esito positivo e produrre un valore oppure fallire senza restituire nulla. Esempi di espressioni fallibili sono l'indicizzazione in un array, poiché un indice non valido avrà esito negativo, e l'utilizzo di operatori di confronto tra valori non comparabili.
Il codice che scrivi non è fallibile per impostazione predefinita. Ad esempio, per scrivere una funzione che può fallire, è necessario aggiungere lo specificatore effetto <decides>
alla definizione della funzione. Attualmente è necessario aggiungere <transacts>
anche quando si usa <decides>
.
Per un elenco completo delle espressioni che sono fallibili, consulta l'elenco delle espressioni in Verse.
Contesto di errore
Un contesto di errore è un contesto in cui è consentita l'esecuzione di espressioni fallibili. Il contesto definisce cosa succede se l'espressione genera errore. Qualsiasi errore all'interno di un contesto di errore causa l'errore dell'intero contesto.
Un contesto di errore consente alle espressioni annidate di essere espressioni di errore, come ad esempio gli argomenti delle funzioni o le espressioni in un'espressione block
.
Un aspetto utile dei contesti di errore in Verse è che sono una forma di esecuzione speculativa, il che significa che si possono provare le azioni senza eseguirne il commit. Quando un'espressione riesce, viene eseguito il commit degli effetti dell'espressione, come ad esempio la modifica del valore di una variabile. Se l'espressione non riesce, viene eseguito il rollback degli effetti dell'espressione, come se l'espressione non si fosse mai verificata.
In questo modo, è possibile eseguire una serie di azioni che accumulano modifiche, ma tali azioni saranno annullate se non riescono in qualsiasi punto.
Affinché questo funzioni, tutte le funzioni chiamate nel contesto di errore devono avere lo specificatore di effetto <transacts>
, altrimenti il compilatore si lamenterà.
Le funzioni definite dall'utente non hanno l'effetto transacts' per impostazione predefinita. È necessario aggiungere un esplicito specificatore
alle loro definizioni. Alcune funzioni native non hanno l'effetto
transacts' e non possono essere chiamate in contesti di fallimento.
Un esempio di funzione nativa senza transacts
potrebbe essere un audio_component con un metodo BeginSound()
. Se il suono viene avviato, anche se viene interrotto potrebbe essere stato notato.
L'elenco seguente comprende tutti i contesti di errore in Verse:
-
La condizione nelle espressioni
if
.if (test-arg-block) { … }
-
Le espressioni di iterazione e le espressioni di filtro nelle espressioni
for
. Nota chefor
è speciale in quanto crea un contesto di fallimento per ogni iterazione. Se le iterazioni sono annidate, anche i contesti di fallimento saranno annidati. Quando un'espressione fallisce, il contesto di fallimento più interno viene interrotto e l'iterazione che lo racchiude, se presente, continua con l'iterazione successiva.for (Item : Collection, test-arg-block) { … }
-
Il corpo di una funzione che include lo specificatore di effetto
<decides>
.IsEqual()<decides><transacts> : void = { … }
-
L'operando per l'operatore
not
.not expression
-
L'operando di sinistra per l'operatore
or
.expression1 or expression2
-
L'inizializzazione di una variabile con il tipo
option
.option{expression}