如何比较F#中的x和y?

时间:2013-09-06 03:46:19

标签: f# pattern-matching

我需要有关比较2个数字的匹配模式的帮助。这样的事情:

let test x y =
   match x with
   | y when x < y -> printfn "less than"
   | y when x > y -> printfn "greater than"
   | _ -> printfn "equal"

不知何故,当x为0且y为200时,它落入“_”情况。我在这里做错了什么?

6 个答案:

答案 0 :(得分:15)

代码的问题在于:当你写:

match x with 
| y when x < y -> (...)

..这意味着您要将x<expr>中的match <expr> with)的值分配给名为y的新变量(<pat>| <pat> when ...)中,然后将此新y(现在包含x的值)与x的值进行比较 - 这样总会返回{{1 }}。您始终可以重命名绑定变量,因此您的代码与编写相同:

false

现在你可以看到为什么它永远不会匹配 - 因为你只是将match x with | newY when x < newY -> (...) 与自身进行比较!

如果你有一些更复杂的结构的输入 - 例如元组或有区别的联合,列表,数组,选项类型等,模式匹配特别有用。但是如果你只是想比较数字,那么使用{{更容易1}}:

x

if中,您实际上并不需要绑定任何变量 - 但John的解决方案演示了如何使其工作 - 简单地说,取变量let test x y = if x < y then printfn "less than" elif x > y then printfn "greater than" else printfn "equal" 和{{1}并将它们分配给新变量matchx(它们具有相同的名称)。

答案 1 :(得分:14)

更好的版本是两个数字上的模式匹配,如此

let test x y =
   match (x,y) with
   | (x,y) when x < y -> printfn "less than"
   | (x,y) when x > y -> printfn "greater than"
   | _ -> printfn "equal"

答案 2 :(得分:5)

如果您咨询Pattern Matching (F#)您使用的模式匹配类型,那么它将是所谓的变量模式,其中匹配案例中的新变量y将被赋予匹配表达式x的值。由于y语句中的match变量会隐藏原始函数参数y,因此在第一个和第二个案例中y只会获得x的值,因此when守卫都失败了。然后,第三个全能比赛案例_开始,所以你得到“平等”回报,如所观察到的。

如果您浏览以下代码段,可以更好地了解会发生什么:

let f x y =
    match x with
    | y -> y

并尝试f arg1 arg2之类的内容;无论f值是什么,arg1都将始终返回arg2

您可以通过将参数比较移动到match表达式,使用与常量模式匹配来表达您的原始意图:

let test x y =
    match sign (Operators.compare x y) with
    | 1 -> "greater than"
    | -1 -> "less then"
    | _ -> "equal"

答案 3 :(得分:2)

模式匹配是一个糟糕的选择,而是使用if

if x < y then
  printfn "less than"
elif x > y then
  printfn "greater than"
else
  printf "equal"

答案 4 :(得分:2)

与John Palmer的回答相似。我认为这样写它会提高你对正在发生的事情的理解:

let test x y = 
    match (x,y) with
    | (a,b) when a < b -> printfn "less than"
    | (a,b) when a > b -> printfn "greater than"
    | _ -> printfn "equal"

简单来说,当您使用Match语句时,模式中的术语(即->之前的部分)会声明新的标识符。当您在模式中重用y时,您将隐藏先前的标识符y并创建一个与您匹配的内容具有相同值的新标识符,在本例中为标识符{ {1}}。换句话说,您始终将x的值与自身进行比较。正如其他人所指出的那样,最好用x语句来完成。

答案 5 :(得分:0)

匹配 x 匹配到匹配 y

let test x y =
       match y with
       | y when x < y -> printfn "less than"
       | y when x > y -> printfn "greater than"
       | _ -> printfn "equal"