OCaml模式与非常量匹配

时间:2012-05-03 16:32:00

标签: pattern-matching ocaml

是否可以对变量进行模式匹配而不是常量值:

# let x = 2 in
let y = 5 in
match 2 with
| x -> "foo"
| y -> "bar"
| _ -> "baz";;
            let y = 5 in
Warning 26: unused variable y.
  let x = 2 in
Warning 26: unused variable x.
  | y -> "bar"
Warning 11: this match case is unused.
  | _ -> "baz";;
Warning 11: this match case is unused.
- : string = "foo"

显然,使用这种语法,x -> "foo"案例会占用一切。有没有办法使它等同于:

match 2 with
| 2 -> "foo"
| 5 -> "bar"
| _ -> "baz"

哪里匹配表达式的值是在运行时确定的?

3 个答案:

答案 0 :(得分:6)

在我看来,when后卫在这里是一个坏主意。初学者倾向于过度使用他们觉得方便的模式匹配语法,这导致他们的应用程序中的细微错误。对于一个会注意到“嘿,| y -> ..这里不是我想要的人”,其他十个人会犯错,不会直接注意到。

你应该劝阻这种易出错的模式。我对初学者的个人建议是从不使用when,而使用模式匹配来解析归纳数据类型的值(例如列表,树,选项等)。整数上的模式匹配几乎总是错误的。

我建议改为使用if ... then .. else if .. then .. else

if z = x then "foo"
else if z = y then "bar"
else "baz"

何时使用when合法?当其余案例确实受益于模式匹配(测试嵌套模式等),或者对匹配值的深度破坏产生的值执行测试时,可以理解。它通常可以通过合并两个分支并在本地使用if..then..else来转换。

一个不方便删除的示例如下(测试结合到解构):

match foo with
| (Baz x) when pred x -> ...
| _ -> ... 

答案 1 :(得分:5)

您需要when警卫:

let x = 2 in
let y = 5 in
match 2 with
| z when z = x -> "foo"
| z when z = y -> "bar"
| _ -> "baz";;

错误消息非常有用。当你使用:

let x = 2 in
...
match 2 with
| x -> "foo"
| ...

新值x会影响先前let-bound中的值x,从而影响第一条错误消息。此外,由于新的x符合所有内容,因此y_以下两种模式显然是多余的。

请注意,匹配常量(match 2 with)并不是一个好主意。

答案 2 :(得分:3)

在这里你正在寻找一个“何时”守卫:

let x = 2 in
let y = 5 in
match 2 with
| x' when x' = x -> "foo"
| y' when y' = y -> "baz"
| _ -> "baz" ;;

......虽然我不确定你为什么想要与常数匹配。