Gestione degli erroriError Handling

La valutazione di un'espressione M produce uno dei risultati seguenti:The result of evaluating an M expression produces one of the following outcomes:

  • Viene generato un singolo valore.A single value is produced.

  • Viene restituito un errore per segnalare che il processo di valutazione dell'espressione non è riuscito a generare un valore.An error is raised, indicating the process of evaluating the expression could not produce a value. Un errore contiene un singolo valore di record che può essere usato per fornire informazioni aggiuntive su ciò che ha causato la valutazione incompleta.An error contains a single record value that can be used to provide additional information about what caused the incomplete evaluation.

Gli errori possono essere restituiti e anche gestiti dall'interno di un'espressione.Errors can be raised from within an expression, and can be handled from within an expression.

Generazione di erroriRaising errors

La sintassi per la generazione di un errore è la seguente:The syntax for raising an error is as follows:

error-raising-expression:error-raising-expression:
      error expression      error expression

Come sintassi abbreviata per i valori di errore possono essere usati valori di testo,Text values can be used as shorthand for error values. ad esempio:For example:

error "Hello, world" // error with message "Hello, world"

I valori di errore completi sono record e possono essere creati tramite la funzione Error.Record:Full error values are records and can be constructed using the Error.Record function:

error Error.Record("FileNotFound", "File my.txt not found",
     "my.txt")

L'espressione precedente è equivalente a:The above expression is equivalent to:

error [ 
    Reason = "FileNotFound", 
    Message = "File my.txt not found", 
    Detail = "my.txt" 
]

Se viene generato un errore, la valutazione dell'espressione corrente viene arrestata e lo stack di valutazione dell'espressione viene rimosso fino a quando non si verifica una delle condizioni seguenti:Raising an error will cause the current expression evaluation to stop, and the expression evaluation stack will unwind until one of the following occurs:

  • Viene raggiunto un campo di record, un membro di sezione o una variabile let (collettivamente definiti voce).A record field, section member, or let variable—collectively: an entry—is reached. La voce è contrassegnata con un errore, il valore di errore viene salvato con tale voce e quindi propagato.The entry is marked as having an error, the error value is saved with that entry, and then propagated. Tutti gli accessi successivi a tale voce provocheranno la generazione di un errore identico.Any subsequent access to that entry will cause an identical error to be raised. Le altre voci del record, della sezione o dell'espressione let non sono necessariamente interessati (a meno che non accedano a una voce contrassegnata in precedenza come errore).Other entries of the record, section, or let expression are not necessarily affected (unless they access an entry previously marked as having an error).

  • Viene raggiunta l'espressione di primo livello.The top-level expression is reached. In questo caso, il risultato della valutazione dell'espressione di primo livello è un errore anziché un valore.In this case, the result of evaluating the top-level expression is an error instead of a value.

  • Viene raggiunta un'espressione try.A try expression is reached. In questo caso, l'errore viene acquisito e restituito come valore.In this case, the error is captured and returned as a value.

Gestione degli erroriHandling errors

Per la gestione di un errore viene usata un'espressione error-handling-expression:An error-handling-expression is used to handle an error:

_error-handling-expression:_error-handling-expression:
      try protected-expression otherwise-clause opt
protected-expression:
      expression
otherwise-clause:
      try protected-expression otherwise-clauseopt
protected-expression:
      expression
otherwise-clause:

      otherwise default-expression
default-expression:
      expression
      otherwise default-expression
default-expression:
      expression

Quando si valuta un'espressione error-handling-expression senza otherwise-clause, sono valide le considerazioni seguenti:The following holds when evaluating an error-handling-expression without an otherwiseclause:

  • Se la valutazione di protected-expression non genera un errore e produce un valore x, il valore prodotto da error-handling-expression è un record nel formato seguente:If the evaluation of the protected-expression does not result in an error and produces a value x, the value produced by the error-handling-expression is a record of the following form:
    [ HasErrors = false, Value = x ]
  • Se la valutazione di protected-expression genera un valore di errore "e", il risultato di error-handling-expression è un record nel formato seguente:If the evaluation of the protected-expression raises an error value e, the result of the error-handling-expression is a record of the following form:
    [ HasErrors = true, Error = e ]

Quando si valuta un'espressione error-handling-expression con otherwise-clause, sono valide le considerazioni seguenti:The following holds when evaluating an error-handling-expression with an otherwiseclause:

  • L'espressione protected-expression deve essere valutata prima di otherwise-clause.The protected-expression must be evaluated before the otherwise-clause.

  • La clausola otherwise-clause deve essere valutata solo se la valutazione di protected-expression genera un errore.The otherwise-clause must be evaluated if and only if the evaluation of the protectedexpression raises an error.

  • Se la valutazione di protected-expression genera un errore, il valore prodotto da error-handling-expression è il risultato della valutazione di otherwise-clause.If the evaluation of the protected-expression raises an error, the value produced by the error-handling-expression is the result of evaluating the otherwise-clause.

  • Gli errori generati durante la valutazione di otherwise-clause vengono propagati.Errors raised during the evaluation of the otherwise-clause are propagated.

Nell'esempio seguente viene illustrata un'espressione error-handling-expression nel caso in cui non venga generato alcun errore:The following example illustrates an error-handling-expression in a case where no error is raised:

let
    x = try "A"
in
    if x[HasError] then x[Error] else x[Value] 
// "A"

Nell'esempio seguente vengono illustrate la generazione di un errore e la relativa gestione:The following example shows raising an error and then handling it:

let
    x = try error "A" 
in
    if x[HasError] then x[Error] else x[Value] 
// [ Reason = "Expression.Error", Message = "A", Detail = null ]

È possibile usare otherwise-clause per sostituire gli errori gestiti da un'espressione try con un valore alternativo:An otherwise clause can be used to replace errors handled by a try expression with an alternative value:

try error "A" otherwise 1 
// 1

Se anche otherwise-clause genera un errore, l'intera espressione try farà lo stesso:If the otherwise clause also raises an error, then so does the entire try expression:

try error "A" otherwise error "B" 
// error with message "B"

Errori negli inizializzatori di record e letErrors in record and let initializers

Nell'esempio seguente viene illustrato un inizializzatore di record con un campo A che genera un errore e a cui accedono altri due campi, B e C.The following example shows a record initializer with a field A that raises an error and is accessed by two other fields B and C. Il campo B non gestisce l'errore generato da A, mentre C lo gestisce.Field B does not handle the error that is raised by A, but C does. Il campo finale D non accede A e pertanto non è interessato dall'errore in A.The final field D does not access A and so it is not affected by the error in A.

[ 
    A = error "A", 
    B = A + 1,
    C = let x =
            try A in
                if not x[HasError] then x[Value]
                else x[Error], 
    D = 1 + 1 
]

Il risultato della valutazione dell'espressione precedente è il seguente:The result of evaluating the above expression is:

[ 
    A = // error with message "A" 
    B = // error with message "A" 
    C = "A", 
    D = 2 
]

La gestione degli errori in M deve essere eseguita in prossimità della causa degli errori in modo da gestire gli effetti dell'inizializzazione di campi differita e delle valutazioni di chiusura posticipate.Error handling in M should be performed close to the cause of errors to deal with the effects of lazy field initialization and deferred closure evaluations. Nell'esempio seguente viene illustrato un tentativo non riuscito di gestione di un errore tramite un'espressione try:The following example shows an unsuccessful attempt at handling an error using a try expression:

let
    f = (x) => [ a = error "bad", b = x ],
    g = try f(42) otherwise 123
in 
    g[a]  // error "bad"

In questo esempio, la definizione g è stata pensata per gestire l'errore generato durante la chiamata a f.In this example, the definition g was meant to handle the error raised when calling f. Tuttavia, l'errore viene generato da un inizializzatore di campo che viene eseguito solo quando necessario e quindi dopo che il record è stato restituito da f e passato tramite l'espressione try.However, the error is raised by a field initializer that only runs when needed and thus after the record was returned from f and passed through the try expression.

Errore di non implementazioneNot implemented error

Quando sviluppa un'espressione, un autore potrebbe voler escludere dall'implementazione alcune parti, ma essere comunque in grado di eseguire l'espressione.While an expression is being developed, an author may want to leave out the implementation for some parts of the expression, but may still want to be able to execute the expression. Un modo per gestire un caso di questo tipo consiste nel generare un errore per le parti non implementate,One way to handle this case is to raise an error for the unimplemented parts. ad esempio:For example:

(x, y) =>
     if x > y then
         x - y
     else
         error Error.Record("Expression.Error", 
            "Not Implemented")

Il simbolo dei puntini di sospensione (...) può essere usato come scorciatoia per error.The ellipsis symbol (...) can be used as a shortcut for error.

not-implemented-expression:not-implemented-expression:
      ...      ...

Il codice che segue, ad esempio, è equivalente all'esempio precedente:For example, the following is equivalent to the previous example:

(x, y) => if x > y then x - y else ...