回

11 / 17 · Error Handling

可预期的失败用 Result

除以零是业务上可能发生的事,不必先变成异常。

Ok 和 Error 也是变体。safe_div 的结果类型逼调用者处理两边。异常更适合「程序坏了」:Match_failure、真正不该出现的状态。

书的建议很具体:能在类型里说清的错误用 Result;跨很多层、而且通常就是崩溃的,再用异常。两者可以互转,但默认别用异常当返回值。

例子

utop
let safe_div x y =
  if y = 0 then Error "除以零" else Ok (x / y)
val safe_div : int -> int -> (int, string) result = <fun>
let render r =
  match r with
  | Ok n -> "ok:" ^ Int.to_string n
  | Error msg -> "err:" ^ msg
val render : (int, string) result -> string = <fun>
render (safe_div 10 2)
- : string = "ok:5"
render (safe_div 10 0)
- : string = "err:除以零"

改一改

改完再跑

解释器覆盖书前半的核心:函数、标签参数、模式、记录、变体、ref、模块,以及简化的 Map 和 JSON。没有 GADT 细化、Async 和独立编译。

先预测,再对照

1 / 2

safe_div 10 0 会?

2 / 2

这种错误为什么不用异常?

在书里读 Error Handling