你能在OCaml中将整数与范围模式匹配吗



作为Graham扫描的一部分,我正在编写一个函数,用于确定直线在某个点是向左转弯还是向右转弯。考虑到我们有一个函数determinant point -> point -> point -> int,其中determinant p0 p1 p2返回det(p0p1,p0p2(,这里是代码:

(* Determines how the line turns at s, when going from t to p*)
let turn t p s =
let det = det s p t in 
if det < 0 then
'r' (* Turning right *)
else if det > 0 then
'l'(* Turning left *)
else 
's' (* Going straight ahead *)
;;

有没有什么方法可以用模式匹配来代替呢?以下是我尝试过的,但显然不起作用:

let turn t p s =
match det s p t with
| < 0 -> 'r'
| 0 -> 's'
| > 0 -> 'l'

;;

(注意,变量/函数名称由类决定;虽然我确实发现单个字母的名称有点令人困惑,但我可能不会更改它们…(

否。

有条件的模式保护可以按照你的建议进行。

let turn t p s =
let det = det s p t in 
if det < 0 then
'r' (* Turning right *)
else if det > 0 then
'l'(* Turning left *)
else 
's' (* Going straight ahead *)'

将变成:

let turn t p s =
match det s p t with
| n when n < 0 -> 'r'
| n when n > 0 -> 'l'
| _            -> 's' 

其中哪一个更清楚地表达了正在发生的事情,这是一个意见问题。

那…呢

随着更复杂的数据的匹配,这个论点变得更有趣。下面是一个非常做作的例子,它的实际实现要好得多。

type num = Int of int | Float of float
let rec cmp a b =
match a, b with
| Int a, Int b ->
if a < b then -1
else if a > b then 1
else 0
| Float a, Float b -> 
if a < b then -1
else a > b then 1
else 0
| Int a, Float b ->
let a = float_of_int a in
if a < b then -1
else a > b then 1
else 0
| Float a, Int b ->
let b = float_of_int b in
if a < b then -1
else a > b then 1
else 0

使用条件保护:

let rec cmp a b =
match a, b with
| Int a, Int b when a < b                -> -1
| Int a, Int b when a > b                ->  1
| Int a, Int b                           ->  0
| Float a, Float b when a < b            -> -1
| Float a, Float b when a > b            ->  1
| Float a, Float b                       ->  0
| Int a, Float b when float_of_int a < b -> -1
| Int a, Float b when float_of_int a > b ->  1
| Int a, Float b                         ->  0
| Float a, Int b when a < float_of_int b -> -1
| Float a, Int b when a > float_of_int b ->  1
| _                                      ->  0

这仍然是一个意见问题,但有条件的警卫可以帮助";"压平";模式匹配中的嵌套条件。

目前只有char(OCaml 5.0之前(支持整数范围。即使是char,实际上也支持部分范围:模式'a'..'d'只不过是'a'|'b'|'c'|'d'的语法糖。但这种编码只能用于像char这样的小整数类型:将区间0..int_max分解为int_max模式对于63位整数来说不是一种选择。

在模式匹配编译器中支持完整的整数范围(或完全有序基元类型上的范围(是可能的,但这将需要大量尚未完成的工作。

最新更新