Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
O resultado da avaliação de uma expressão M produz um dos seguintes resultados:
Um único valor é produzido.
Um erro é gerado, indicando que o processo de avaliação da expressão não poderia produzir um valor. Um erro contém um único valor de registro que pode ser usado para fornecer informações adicionais sobre o que causou a avaliação incompleta.
Os erros podem ser gerados a partir de uma expressão e podem ser tratados a partir de uma expressão.
Suscitar erros
A sintaxe para gerar um erro é a seguinte:
expressão de aumento de erro:
error
expressão
A expressão que está a ser elevada deve ser avaliada para um valor de erro.
Na forma canónica, um valor de erro é um registo com a seguinte estrutura, tendo valores de campo compatíveis com os tipos indicados:
[
Reason = ..., // nullable text
Message = ..., // nullable text
Detail = ..., // any
Message.Format = ..., // nullable text
Message.Parameters = ..., // nullable list
ErrorCode = ... // any
]
Todos os campos de registo acima são opcionais e, por isso, podem ser omitidos. Quaisquer campos adicionais incluídos no registo serão ignorados e, por isso, não incluídos no erro apresentado.
Message.Format pode conter marcadores de interpolação de strings na forma de #{x}, onde x é um índice baseado em zero. Quando surge um erro com um Message.Format não nulo, a interpolação será realizada usando Message.Format como string de formato e Message.Parameters como valores a serem aplicados posicionalmente. A saída resultante tornar-se-á a Mensagem do erro levantado.
Por exemplo:
error [
Message.Format = "Unexpected value '#{0}' in field #{1}",
Message.Parameters = {"???", "Customer"}
]
Resultará no seguinte erro:
[
ErrorCode = null,
Reason = null,
Message = "Unexpected value '???' in field Customer",
Detail = null,
Message.Format = "Unexpected value '#{0}' in field #{1}",
Message.Parameters = {"???", "Customer"}
]
Os valores de texto podem ser usados como abreviatura para valores de erro. Por exemplo:
error "Hello, world" // error with message "Hello, world"
Os valores de erro completos são registros e podem ser construídos usando a Error.Record função:
error Error.Record("FileNotFound", "File my.txt not found",
"my.txt")
A expressão acima é equivalente a:
error [
Reason = "FileNotFound",
Message = "File my.txt not found",
Detail = "my.txt"
]
Gerar um erro fará com que a avaliação de expressão atual seja interrompida e a pilha de avaliação de expressão será desenrolada até que ocorra uma das seguintes situações:
Um campo de registro, membro de seção ou variável let — coletivamente: uma entrada — é alcançado. A entrada é marcada como tendo um erro, o valor do erro é salvo com essa entrada e, em seguida, propagado. Qualquer acesso subsequente a essa entrada causará um erro idêntico a ser gerado. Outras entradas do registro, seção ou expressão let não são necessariamente afetadas (a menos que acessem uma entrada marcada anteriormente como tendo um erro).
A expressão de nível superior é atingida. Nesse caso, o resultado da avaliação da expressão de nível superior é um erro em vez de um valor.
Chega-se a uma
tryexpressão. Nesse caso, o erro é capturado e retornado como um valor.
Processar erros
Uma expressão de manipulação de erros (conhecida informalmente como "expressão try") é usada para lidar com um erro:
error-handling-expression:
try
opt pelo manipuladorde erros de expressão protegida
Expressão-protegida:
expressão
manipulador de erros:
cláusula contrária
Cláusula de captura
cláusula contrária:
otherwise
expressão-padrão
expressão-padrão:
expressão
Cláusula de captura:
catch
Função de captura
Função de captura:
(
nome-parâmetro)=>
O seguinte vale ao avaliar uma expressão de manipulação de erros sem um manipulador de erros:
- Se a avaliação da expressão protegida não resultar em um erro e produzir um valor x, o valor produzido pela expressão de manipulação de erros será um registro da seguinte forma:
[ HasErrors = false, Value = x ]
- Se a avaliação da expressão protegida gerar um valor de erro e, o resultado da expressão de tratamento de erros será um registro da seguinte forma:
[ HasErrors = true, Error = e ]
O seguinte vale ao avaliar uma expressão de manipulação de erros com um manipulador de erros:
A expressão protegida deve ser avaliada antes do manipulador de erros.
O manipulador de erros deve ser avaliado se e somente se a avaliação da expressão protegida gerar um erro.
Se a avaliação da expressão protegida gerar um erro, o valor produzido pela expressão de manipulação de erros é o resultado da avaliação do manipulador de erros.
Os erros gerados durante a avaliação do manipulador de erros são propagados.
Quando o manipulador de erros que está sendo avaliado é uma cláusula catch, a função catch-é invocada. Se essa função aceitar um parâmetro, o valor do erro será passado como seu valor.
O exemplo a seguir ilustra uma expressão de manipulação de erros em um caso em que nenhum erro é gerado:
let
x = try "A"
in
if x[HasError] then x[Error] else x[Value]
// "A"
O exemplo a seguir mostra como gerar um erro e, em seguida, manipulá-lo:
let
x = try error "A"
in
if x[HasError] then x[Error] else x[Value]
// [ Reason = "Expression.Error", Message = "A", Detail = null ]
O exemplo anterior pode ser reescrito com menos sintaxe usando uma cláusula catch-com uma função catch-que aceita um parâmetro:
let
x = try error "A" catch (e) => e
in
x
// [ Reason = "Expression.Error", Message = "A", Detail = null ]
Uma cláusula de outra forma pode ser usada para substituir erros manipulados por uma expressão try por um valor alternativo:
try error "A" otherwise 1
// 1
Uma cláusula catch-com uma função catch-parâmetro zero é efetivamente uma sintaxe alternativa mais longa para uma cláusula de outra forma:
try error "A" catch () => 1
// 1
Se o manipulador de erros também gerar um erro, toda a expressão try também gera:
try error "A" otherwise error "B"
// error with message "B"
try error "A" catch () => error "B"
// error with message "B"
try error "A" catch (e) => error "B"
// error with message "B"
Erros nos inicializadores de registro e permissão
O exemplo a seguir mostra um inicializador de registro com um campo A que gera um erro e é acessado por dois outros campos B e C. O campo B não lida com o erro gerado pelo A, mas C o faz. O campo D final não acessa A e, portanto, não é afetado pelo erro em 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
]
O resultado da avaliação da expressão acima é:
[
A = // error with message "A"
B = // error with message "A"
C = "A",
D = 2
]
O tratamento de erros em M deve ser realizado próximo à causa dos erros para lidar com os efeitos da inicialização de campo preguiçoso e avaliações de fechamento diferido. O exemplo a seguir mostra uma tentativa malsucedida de manipular um erro usando uma try expressão:
let
f = (x) => [ a = error "bad", b = x ],
g = try f(42) otherwise 123
in
g[a] // error "bad"
Neste exemplo, a definição g destinava-se a lidar com o erro gerado ao chamar f. No entanto, o erro é gerado por um inicializador de campo que só é executado quando necessário e, portanto, depois que o registro foi retornado de f e passado pela try expressão.
Erro não implementado
Enquanto uma expressão está sendo desenvolvida, um autor pode querer deixar de fora a implementação para algumas partes da expressão, mas ainda pode querer ser capaz de executar a expressão. Uma maneira de lidar com esse caso é gerar um erro para as partes não implementadas. Por exemplo:
(x, y) =>
if x > y then
x - y
else
error Error.Record("Expression.Error",
"Not Implemented")
O símbolo de reticências (...) pode ser usado como um atalho para error.
expressão não implementada:
...
Por exemplo, o seguinte é equivalente ao exemplo anterior:
(x, y) => if x > y then x - y else ...