OCaml 模式顺序匹配最佳实践

OCaml order of pattern matches best practice

从性能的角度来看,我想知道匹配模式的顺序是否会影响函数的效率,或者它与预期的不同匹配的比例有更多关系(即如果一个模式比其他模式发生得更多, 它应该出现得更早)。

(* a function to return the smaller of two int options, or None if both are None. If exactly one argument is None, return the other. *)

let min_option (x: int option) (y: int option) : int option =
  match x, y with
    None, None -> None
    | Some x, None -> Some x
    | None, Some y -> Some y
    | Some x, Some y -> if x < y then Some x else Some y

let () = assert((min_option (Some 10) (Some 11)) = Some 10);;

OCaml 中的模式匹配算法非常聪明,因此您无需担心匹配顺序。如果您对某个主题感兴趣,请从这里开始阅读 Whosebug post

上述规则有一些例外:首先,如果它们重叠,函数的语义可能取决于匹配的顺序;其次,如果你对数据进行模式匹配,比如字符串或整数,那么它将被编译成有点类似于 if/else 系列,其中有一些 optimizations.

最后问原来的问题,我不知道如何以有效的方式编写模式匹配的最佳实践。

更新:

以防万一,我显然认为提供的示例是合成的,但对于那些将来会阅读我们的人来说。您根本不需要编写此函数,因为 pervasive 的 min 是通用多态函数,已经在选项上具有预期的行为。因此,您的函数与 min x y 完全相同(在语义上)。但是,如果你真的对优化感兴趣,例如,如果你在一个紧密的循环中使用它,那么你可以像这样重写它:

let min x y : int option =
  match x, y with
  | v, None | None, v -> v
  | Some p, Some q -> if p < q then x else y

这将产生有效的代码,不会执行对多态比较函数的 C 调用,也不执行任何分配。但是一如既往,你应该跟踪你的程序来找出这个函数确实是一个瓶颈。

这与您的问题并没有太大关系,但如果您关心性能,您可能应该以不同的方式编写匹配:

match x, y with
  | v, None
  | None, v -> v
  | (Some x as v1), (Some y as v2) -> if x < y then v1 else v2

这样你就可以避免分配 Some 块。