4

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

# 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"case 会处理一切。有没有办法让它等同于:

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

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

4

3 回答 3

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 -> ...
| _ -> ... 
于 2012-05-04T11:22:20.250 回答
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隐藏了x先前 let-bound 中的值,因此是第一条错误消息。此外,由于 newx匹配所有内容,y因此 和_的以下两个模式显然是多余的。

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

于 2012-05-03T16:39:55.007 回答
3

“何时”守卫是您在这里寻找的:

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

...尽管我不确定您为什么要与常量匹配。

于 2012-05-03T16:42:26.633 回答