关于模式匹配的用法

时间:2013-09-16 16:48:14

标签: f# pattern-matching

我认为这两个功能是一样的,但似乎我错了。 我用这种方式定义了两个函数f和g:

let rec f n k =
   match k with
   |_ when (k < 0) || (k > n) -> 0
   |_ when k = n -> 100
   |_ -> (f n (k+1)) + 1

let rec g n k =
   match k with
   |_ when (k < 0) || (k > n) -> 0
   | n -> 100
   |_ -> (g n (k+1)) + 1

let x = f 10 5
let y = g 10 5

结果是:

val x : int = 105
val y : int = 100

有谁能告诉我这两个功能之间的区别是什么?


修改

为什么在这里工作?

let f x =
   match x with
   | 1 -> 100
   | 2 -> 200
   |_ -> -1

List.map f [-1..3]

我们得到了

val f : x:int -> int
val it : int list = [-1; -1; 100; 200; -1]

2 个答案:

答案 0 :(得分:3)

区别在于

match k with 
... 
when k = n -> 100

是在某个特定条件为真时匹配的情况(k = n)。条件中使用的n是指作为函数参数绑定的n。另一方面

match k with 
...
n -> 100

是一种只需要将k与模式变量n匹配的情况,它始终可以成功。模式中的n与传递给函数的n不同n

为了进行比较,请尝试代码

let rec g n k =
   match k with
   |_ when (k < 0) || (k > n) -> 0
   | n -> n
   |_ -> (g n (k+1)) + 1

你应该看到,当你到达第二种情况时,返回的值是模式变量n的值,它已绑定到k的值。

MSDN F# Language Reference, Pattern Matching

的“变量模式”部分描述了此行为
  

变量模式

     

变量模式将匹配的值分配给变量   name,然后可以在执行表达式中使用    -> 符号的右侧。可变模式单独匹配任何模式   输入,但变量模式通常出现在其他模式中,   因此可以实现更复杂的结构,如元组和数组   被分解成变量。以下示例演示了一个   元组模式中的变量模式。

let function1 x =
    match x with
    | (var1, var2) when var1 > var2 -> printfn "%d is greater than %d" var1 var2 
    | (var1, var2) when var1 < var2 -> printfn "%d is less than %d" var1 var2
    | (var1, var2) -> printfn "%d equals %d" var1 var2

function1 (1,2)
function1 (2, 1)
function1 (0, 0)

Match Expressions中更深入地描述了when的使用。

答案 1 :(得分:0)

第一个函数是ok,它递归调用n-k次,并在与条件where k = n匹配时返回100。因此,它返回所有调用,增加1 n-k次。在您的示例中,使用n=10k=5,结果是105。

问题是第二个功能。我测试了here。请参阅我将模式n->100更改为z->100,它仍然匹配,并且从不以递归方式调用自身。因此,如果在第一个条件中没有失败,它总是返回100。我认为F#不允许这种匹配,所以最好放一个条件来获得你想要的东西。