我一直试图了解F#的各个部分(我来自更多的C#背景),解析器对我很感兴趣,所以我跳过关于F#解析器组合器的博客文章:
http://santialbo.com/blog/2013/03/24/introduction-to-parser-combinators
其中一个样本是:
/// If the stream starts with c, returns Success, otherwise returns Failure
let CharParser (c: char) : Parser<char> =
let p stream =
match stream with
| x::xs when x = c -> Success(x, xs)
| _ -> Failure
in p //what does this mean?
Run Code Online (Sandbox Code Playgroud)
但是,这个代码让我感到困惑的一件事就是in p
声明.我in
在MSDN文档中查找了关键字:
http://msdn.microsoft.com/en-us/library/dd233249.aspx
我也发现了这个早先的问题:
这些似乎都没有相同的用法.唯一合适的是这是一个流水线构造.
在let x = ... in expr
你可以定义一些变量绑定x
,然后可以在expr中使用.
在这种情况下p
,一个函数接受一个参数stream
,然后返回Success
或者Failure
根据匹配的结果返回,并且该函数由CharParser
函数返回.
例如,F#light语法自动嵌套let .. in
绑定
let x = 1
let y = x + 2
y * z
Run Code Online (Sandbox Code Playgroud)
是相同的
let x = 1 in
let y = x + 2 in
y * z
Run Code Online (Sandbox Code Playgroud)
因此,in
这里不需要,函数可以简单地写成
let CharParser (c: char) : Parser<char> =
let p stream =
match stream with
| x::xs when x = c -> Success(x, xs)
| _ -> Failure
p
Run Code Online (Sandbox Code Playgroud)
李的答案解释了这个问题.在F#中,in
关键字是来自早期函数语言的遗产,这些语言启发了F#并且需要它 - 即来自ML和OCaml.
可能值得补充的是,F#中只有一种情况仍然需要in
- 也就是说,当你想let
在一行上写一个表达式时.例如:
let a = 10
if (let x = a * a in x = 100) then printfn "Ok"
Run Code Online (Sandbox Code Playgroud)
这是一种有点时髦的编码风格,我通常不会使用它,但你确实需要in
这样写它.您可以随时将其拆分为多行:
let a = 10
if ( let x = a * a
x = 100 ) then printfn "Ok"
Run Code Online (Sandbox Code Playgroud)