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