1

我以为这两个功能是一样的,但似乎我错了。我以这种方式定义了两个函数 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]
4

2 回答 2

3

不同之处在于

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

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

match k with 
...
n -> 100

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

为了比较,请尝试代码

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的 Variable Patterns 部分中进行了描述:

可变模式

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

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)

匹配表达式when中更深入地描述了的使用。

于 2013-09-16T19:31:02.813 回答
0

第一个函数没问题,它递归地调用自身n-k次数,并在与条件匹配时返回 100 where k = n。因此,它返回所有调用加 1n-k次。以您的示例为例,n=10结果k=5为 105 是可以的。

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

于 2013-09-16T17:04:47.940 回答