繁体   English   中英

F#与参数匹配的模式

[英]F# Pattern matching with an argument

这可能很简单,但有人可以解释为什么下面的模式匹配不合理吗? 它说其他规则,例如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

第一个示例中的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

如您所见,let-bound n影响输入参数n

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

你的第一个模式

| m -> 

有一个变量m ,可以匹配任何值。 你在想m in

let m = n 

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

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

你需要一个when子句 ,看看后卫

| m when m = n ->

如果您将匹配重写为以下内容,您可能会更好地理解它:

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"

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

那个部分

| pattern ->

图案其实是在匹配/功能范围“新局部变量”(即一个拉姆达),而不是相同的正外部。

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

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

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

或者在http://fsharpforfunandprofit.com/posts/match-expression/上通过示例和您从未了解过的内容进行详尽的解释(最好的意思!)

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM