这可能很简单,但有人可以解释为什么以下模式匹配不合理吗?它说其他规则,例如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"
那为什么它可以直接匹配n
或m
?
答案 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/
的情况下,通过实例和您从未了解过的详尽解释(最好的意思!)是的,匹配表达式最初可能会令人困惑。至少对我来说。