F#与参数匹配的模式

时间:2016-01-19 12:18:49

标签: f# pattern-matching

这可能很简单,但有人可以解释为什么以下模式匹配不合理吗?它说其他规则,例如1,0,_永远不会匹配。

let matchTest(n : int) = 
    let ran = new Random()
    let i = ran.Next(0, 2)
    match i with
    | n -> printfn "%i" n
    | 1 -> printfn "1"
    | 0 -> printfn "0"
    | _ -> printfn "impossible"

同样的事情:

let matchTest(n : int) = 
    let ran = new Random()
    let i = ran.Next(0, 2)
    let m = n
    match i with
    | m -> printfn "%i" m
    | 1 -> printfn "1"
    | 0 -> printfn "0"
    | _ -> printfn "impossible"

那为什么它可以直接匹配nm

3 个答案:

答案 0 :(得分:6)

第一个示例中的etiket.setOpenExternalLinks(True) etiket.setTextInteractionFlags(Qt.TextBrowserInteraction) etiket.setTextFormat(Qt.RichText) 是一个占位符符号,如果匹配成功则会填充该符号。这和写作一样:

n

如果匹配成功,则符号let matchTest(n : int) = let ran = new Random() let i = ran.Next(0, 2) match i with | x -> printfn "%i" x | 1 -> printfn "1" | 0 -> printfn "0" | _ -> printfn "impossible" 会填充x的值,然后可以在i的右侧使用。此匹配始终成功,这解释了为什么其他匹配案例无法访问。

在你的情况下,恰好你已经命名了匹配变量->,它与输入参数的名称相同。

但是,它的价值并不相同。相反,会发生一个新值也称为 n,并且不再可以访问之前的n

这是一种名为阴影的语言功能。

你也可以在模式匹配之外看到它:

n

使用示例:

let foo n =
    let n = 1
    n

正如您所看到的,绑定> foo 42;; val it : int = 1 > foo 1337;; val it : int = 1 会影响输入参数n

OP中第二个与n匹配的示例是第一个的变体,因此适用相同的解释。

答案 1 :(得分:3)

你的第一个模式

| m -> 

有一个变量m,可以匹配任何值。您正在考虑

中的m
let m = n 

是相同的m变量,而不是。

因此,剩下的模式永远不会匹配,因为第一个模式匹配所有输入。

您需要when clause,请参阅guard

| m when m = n ->

答案 2 :(得分:3)

如果您按照以下内容重写比赛,您可能会更好地理解它:

let matchTest(n : int) = 
    let ran = new Random()
    ran.Next(0, 2)
    |> function
       | n -> printfn "%i" n
       | 1 -> printfn "1"
       | 0 -> printfn "0"
       | _ -> printfn "impossible"

重点是匹配(或函数)采用参数,但内部的所有内容都在本地声明,因为您的代码最初是在编写的。此时(外部)没有关闭。

部分

| pattern ->

模式实际上是匹配/函数范围(即lambda)中的“新局部变量”,而 NOT 与n外部相同。

然后,您需要为此“新创建的变量”应用保护子句:

| pattern when pattern = n -> printfn "%i" n

另见https://msdn.microsoft.com/en-us/library/dd233242.aspx

或者在http://fsharpforfunandprofit.com/posts/match-expression/

的情况下,通过实例和您从未了解过的详尽解释(最好的意思!)

是的,匹配表达式最初可能会令人困惑。至少对我来说。