如何将多个条件模式与一个结果匹配?
How to match multiple conditional patterns with one result?
尝试编译以下函数会导致错误:
let balance (left : 'a t) (ele : 'a) (right : 'a t) : 'a t =
match left,ele,right with
| N (d',N (_,a,x,b),y,c),z,d when d' - depth d > 1 && ele < y
| N (d',a,x,N (_,b,y,c)),z,d when d' - depth d > 1 && ele > x
| a,x,N (d',N (_,b,y,c),z,d) when d' - depth a > 1 && ele < z
| a,x,N (d',b,y,N (_,c,z,d)) when d' - depth a > 1 && ele > y
-> new_node (new_node a x b) y (new_node c z d)
| _ -> new_node left ele right
但是,以下两个函数都可以正常编译:
let balance (left : 'a t) (ele : 'a) (right : 'a t) : 'a t =
match left,ele,right with
| N (d',N (_,a,x,b),y,c),z,d
| N (d',a,x,N (_,b,y,c)),z,d
| a,x,N (d',N (_,b,y,c),z,d)
| a,x,N (d',b,y,N (_,c,z,d))
-> new_node (new_node a x b) y (new_node c z d)
| _ -> new_node left ele right
let balance (left : 'a t) (ele : 'a) (right : 'a t) : 'a t =
match left,ele,right with
| N (d',N (_,a,x,b),y,c),z,d when d' - depth d > 1 && ele < y
-> new_node (new_node a x b) y (new_node c z d)
| _ -> new_node left ele right
如何获得第一个块中指定的行为?显然,我可以将第七行复制到前面的每个模式,但我不想这样做。
没错,这是 OCaml 模式的限制。
当你这样写的时候:
match x with
| 1
| 2 -> f x
你实际上只写了一个看起来像这样的模式:
match x with
| (1 | 2) -> f x
所以这个(如果允许的话):
match x with
| 1 when a
| 2 when b -> f x
相当于这样的东西:
match x with
| (1 when a | 2) when b -> f x
换句话说,您要做的是将 when
子句添加到模式的中间。这不受支持。它们只是 match
的特征,而不是一般模式的特征。
作为 Jeffrey Scofield 已经说过的内容的补充,请注意以下陷阱。
match 42 with
| 1
| n when n mod 2 = 0 -> "foo"
| n -> "bar"
或等效地:
match 42 with
| (1 | n) when n mod 2 = 0 -> "foo"
| n -> "bar"
两者都会让您出现此错误:
Error: Variable n must occur on both sides of this | pattern
when
条件保护必须为 任一 模式工作。这就是以下内容起作用的原因。
match (3, 2) with
| (1, n)
| (3, n) when n mod 2 = 0 -> "foo"
| n -> "bar"
等价于:
match (3, 2) with
| ((1, n) | (3, n)) when n mod 2 = 0 -> "foo"
| n -> "bar"
如果使用与 |
连接的模式将相同的名称绑定到不同的值,请做好编译器警告的准备。
尝试编译以下函数会导致错误:
let balance (left : 'a t) (ele : 'a) (right : 'a t) : 'a t =
match left,ele,right with
| N (d',N (_,a,x,b),y,c),z,d when d' - depth d > 1 && ele < y
| N (d',a,x,N (_,b,y,c)),z,d when d' - depth d > 1 && ele > x
| a,x,N (d',N (_,b,y,c),z,d) when d' - depth a > 1 && ele < z
| a,x,N (d',b,y,N (_,c,z,d)) when d' - depth a > 1 && ele > y
-> new_node (new_node a x b) y (new_node c z d)
| _ -> new_node left ele right
但是,以下两个函数都可以正常编译:
let balance (left : 'a t) (ele : 'a) (right : 'a t) : 'a t =
match left,ele,right with
| N (d',N (_,a,x,b),y,c),z,d
| N (d',a,x,N (_,b,y,c)),z,d
| a,x,N (d',N (_,b,y,c),z,d)
| a,x,N (d',b,y,N (_,c,z,d))
-> new_node (new_node a x b) y (new_node c z d)
| _ -> new_node left ele right
let balance (left : 'a t) (ele : 'a) (right : 'a t) : 'a t =
match left,ele,right with
| N (d',N (_,a,x,b),y,c),z,d when d' - depth d > 1 && ele < y
-> new_node (new_node a x b) y (new_node c z d)
| _ -> new_node left ele right
如何获得第一个块中指定的行为?显然,我可以将第七行复制到前面的每个模式,但我不想这样做。
没错,这是 OCaml 模式的限制。
当你这样写的时候:
match x with
| 1
| 2 -> f x
你实际上只写了一个看起来像这样的模式:
match x with
| (1 | 2) -> f x
所以这个(如果允许的话):
match x with
| 1 when a
| 2 when b -> f x
相当于这样的东西:
match x with
| (1 when a | 2) when b -> f x
换句话说,您要做的是将 when
子句添加到模式的中间。这不受支持。它们只是 match
的特征,而不是一般模式的特征。
作为 Jeffrey Scofield 已经说过的内容的补充,请注意以下陷阱。
match 42 with
| 1
| n when n mod 2 = 0 -> "foo"
| n -> "bar"
或等效地:
match 42 with
| (1 | n) when n mod 2 = 0 -> "foo"
| n -> "bar"
两者都会让您出现此错误:
Error: Variable n must occur on both sides of this | pattern
when
条件保护必须为 任一 模式工作。这就是以下内容起作用的原因。
match (3, 2) with
| (1, n)
| (3, n) when n mod 2 = 0 -> "foo"
| n -> "bar"
等价于:
match (3, 2) with
| ((1, n) | (3, n)) when n mod 2 = 0 -> "foo"
| n -> "bar"
如果使用与 |
连接的模式将相同的名称绑定到不同的值,请做好编译器警告的准备。