带参数的F#模式匹配
这可能很简单,但有人能解释为什么下面的模式匹配不合理吗?它说其他规则,例如1,0,将永远不会匹配带参数的F#模式匹配,f#,pattern-matching,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 "
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
| m ->
具有可匹配任何值的变量m
。您认为m
在
let m = n
是相同的m
变量,但不是
因此,剩余的模式将永远不会匹配,因为第一个模式匹配所有输入
你需要一份工作,明白吗
第一个示例中的
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-boundn
对输入参数n
进行了阴影处理
OP中的第二个示例,您在
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"
关键是匹配(或函数)接受一个param,但内部的所有内容都是在最初编写代码时本地声明的。在(外部)n的这一点上不应用闭合
角色
| pattern ->
模式实际上是匹配/函数范围内的“新局部变量”(即lambda),并且与外部的n不同
然后,您需要为这个“新创建的变量”应用guard子句:
另见
或者用例子和你不知道你应该学的东西(最好的意思!)进行详尽的解释
是的,匹配表达式一开始可能会让人困惑。至少对我来说是这样。我知道如何修复它,但不明白为什么它不能像这样。我想我没有完全理解模式匹配背后发生了什么,我认为这是一个简单的比较,而不是。这真的是阴影吗?而不是真正的范围界定?既然图案是一个lambda?还是我的另一个答案错了?或者阴影和范围/λ是否相同?最后但并非最不重要的一点:我困惑了吗?@Helgereneuroholm我同意阴影绝对是正确的术语。虽然作用域起到了一定的作用,但你并不是完全错误的,如果说关键的方面是嵌套正在进行——记住(搜索轻语法)在F#中,每一行都隐含着一个连接到下一个表达式的
| pattern ->
| pattern when pattern = n -> printfn "%i" n