多变量的模式匹配

15

我刚接触 F#,还没有找到如何正确地执行以下操作的方法。

let fun1 a b =
match a b with
| a + b > 0 -> fun2
| a + b < 0 -> fun3

我必须使用模式匹配来完成作业,但我不知道如何正确地做。我认为可以使用元组如下:

let fun1 (a,b) =
match (a,b) with
| (a,b) when a + b > 0 -> fun2
| (a,b) when a + b < 0 -> fun3

但那也行不通。我该怎么办?

3个回答

19

你的想法是正确的,只是忘记了在 F# 中缩进很重要。添加空格可以让你的解决方案正常工作:

let fun1 (a,b) =  
    match (a,b) with
    | (a,b) when a + b > 0 -> fun2
    | (a,b) when a + b < 0 -> fun3

这个模式实际上匹配了两次,因此我们可能需要重新编写它:

let fun1 t = function 
    | (a,b) when a + b > 0 -> fun2
    | (a,b) when a + b < 0 -> fun3

编译器/解释器会允许这样做,并发出警告:

警告 FS0025: 在此表达式上存在不完整的模式匹配。

我会把去掉警告作为一项练习 :-)
PS. 你能够坦率地承认这是一份作业,很好。

1
非常欢迎。一定要注意下面kvs的回答,他提出了我没有提到的好观点。 - Søren Debois

10

Søren Debois是正确的。以下是一些其他的注意事项:

  1. ab已经在作用域内,所以你不需要匹配它们,你可以匹配任何内容:

let fun1 (a,b) =
    match () with
    | () when a + b > 0 -> fun2
    | () when a + b < 0 -> fun3
  • 因此,使用 if 语句可能更符合惯用语。

  • 显然,您忽略了+=0的情况;请注意,编译器始终假定 when 子句可能不包含任何内容,因此即使添加了 | () when a + b = 0 -> ... 情况,您仍将收到警告,指出某些情况可能未被处理;您需要改为使用 | () -> ...| _ -> ...

  • 对于形式为let f <pattern> = match <same pattern> with |...的定义,有一种内置的快捷方式,即let f = function |...。您可以这样使用:

  • let fun1 = function
    | (a,b) when a + b > 0 -> fun2
    | ...
    

    请注意,现在ab不再受函数定义的限制,因此我的第一个注释中的想法不适用了,您必须在模式中引入它们。


    谢谢,这有助于让我的代码更好看和更优秀! - Javier Lorenzini

    3
    您可以在匹配子句中添加以下内容:
    let fun2() = ()
    let fun3() = ()
    let fun1 a b =
        match (a+b) with
            | res when res > 0 -> fun2
            | res when res < 0 -> fun3
            | _ -> raise (new System.NotImplementedException())
    

    涵盖你的模式的所有情况,这是良好的实践 :-)

    1
    很好的选择,在求和时进行匹配,而不是元组。 - N_A

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接