我认为这两个功能是一样的,但似乎我错了。 我用这种方式定义了两个函数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]
答案 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=10
和k=5
,结果是105。
问题是第二个功能。我测试了here。请参阅我将模式n->100
更改为z->100
,它仍然匹配,并且从不以递归方式调用自身。因此,如果在第一个条件中没有失败,它总是返回100。我认为F#不允许这种匹配,所以最好放一个条件来获得你想要的东西。