计算 M 表达式的结果会产生以下结果之一:
- 产生单个值。
- 出现错误,表明对表达式求值的过程无法产生值。错误包含单个记录值,可用于提供有关导致评估不完整的原因的附加信息。
错误可以从表达式中引发,也可以从表达式中处理。
引发错误
引发错误的语法如下:
错误引发表达式:
error
表达式
文本值可用作错误值的简写。例如:
复制
代码语言:javascript复制error "Hello, world" // error with message "Hello, world"
完整的错误值是记录,可以使用以下Error.Record
函数构造:
复制
代码语言:javascript复制error Error.Record("FileNotFound", "File my.txt not found",
"my.txt")
上面的表达式等价于:
复制
代码语言:javascript复制error [
Reason = "FileNotFound",
Message = "File my.txt not found",
Detail = "my.txt"
]
引发错误将导致当前表达式计算停止,并且表达式计算堆栈将展开,直到发生以下任一情况:
- 到达记录字段、部分成员或 let 变量——统称为一个条目。该条目被标记为有错误,错误值与该条目一起保存,然后传播。对该条目的任何后续访问都将导致引发相同的错误。记录、节或 let 表达式的其他条目不一定会受到影响(除非它们访问先前标记为有错误的条目)。
- 达到了顶级表达式。在这种情况下,评估顶级表达式的结果是错误而不是值。
try
达到了一个表达式。在这种情况下,错误被捕获并作为值返回。
处理错误
一个错误处理表达式是用来处理一个错误:
_error-handling-expression:
try
protected-expression other-clause opt
protected-expression:
expression
other-clause:
otherwise
default-expression
default-expression:
expression
的评价时以下成立错误处理表达没有otherwiseclause:
- 如果protected-expression 的求值没有导致错误并产生值x,则error-handling-expression 产生的值是以下形式的记录:
复制
代码语言:javascript复制 [ HasErrors = false, Value = x ]
- 如果受保护表达式的求值产生错误值 e,则错误处理表达式的结果是以下形式的记录:
复制
代码语言:javascript复制 [ HasErrors = true, Error = e ]
的评价时以下成立错误处理表达与otherwiseclause:
- 必须在其他子句之前评估受保护的表达式。
- 当且仅当对受保护表达式的求值引发错误时,必须对其他子句求值。
- 如果protected-expression的求值引发错误,则error-handling-expression产生的值是对others-clause 求值的结果。
- 传播在其他条款评估期间引发的错误。
以下示例说明了未引发错误的情况下的错误处理表达式:
复制
代码语言:javascript复制let
x = try "A"
in
if x[HasError] then x[Error] else x[Value]
// "A"
以下示例显示引发错误然后处理它:
复制
代码语言:javascript复制let
x = try error "A"
in
if x[HasError] then x[Error] else x[Value]
// [ Reason = "Expression.Error", Message = "A", Detail = null ]
可以使用 else 子句将 try 表达式处理的错误替换为替代值:
复制
代码语言:javascript复制try error "A" otherwise 1
// 1
如果 else 子句也引发错误,那么整个 try 表达式也会引发错误:
复制
代码语言:javascript复制try error "A" otherwise error "B"
// error with message "B"
记录错误和 let 初始值设定项
以下示例显示了一个记录初始值设定项,其字段A
引发错误并由其他两个字段B
和访问C
。FieldB
不处理由 引发的错误A
,但C
会处理。final 字段D
不会访问A
,因此它不受A
.
复制
代码语言:javascript复制[
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
]
对上述表达式求值的结果是:
复制
代码语言:javascript复制[
A = // error with message "A"
B = // error with message "A"
C = "A",
D = 2
]
M 中的错误处理应该在接近错误原因的地方执行,以处理延迟字段初始化和延迟闭包评估的影响。以下示例显示了使用try
表达式处理错误的失败尝试:
复制
代码语言:javascript复制let
f = (x) => [ a = error "bad", b = x ],
g = try f(42) otherwise 123
in
g[a] // error "bad"
在此示例中,定义g
旨在处理调用f
. 但是,该错误是由字段初始值设定项引发的,该初始值设定项仅在需要时运行,因此在从 f 返回记录并通过try
表达式之后。
未实现错误
在开发表达式时,作者可能希望省略表达式某些部分的实现,但仍希望能够执行表达式。处理这种情况的一种方法是为未实现的部分引发错误。例如:
复制
代码语言:javascript复制(x, y) =>
if x > y then
x - y
else
error Error.Record("Expression.Error",
"Not Implemented")
省略号 ( ...
) 可用作 的快捷方式error
。
未实现的表达式:
...
例如,以下等效于前面的示例:
复制
代码语言:javascript复制(x, y) => if x > y then x - y else ...