我需要有关比较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时,它落入“_”情况。我在这里做错了什么?
答案 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}并将它们分配给新变量match
和x
(它们具有相同的名称)。
答案 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"