3

我一直在尝试了解 F# 的各个方面(我来自更多的 C# 背景),并且解析器让我感兴趣,所以我跳到了这篇关于 F# 解析器组合器的博客文章:

http://santibo.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?

然而,让我对这段代码感到困惑的一件事是in p声明。我在 MSDN 文档中查找了in关键字:

http://msdn.microsoft.com/en-us/library/dd233249.aspx

我还发现了这个较早的问题:

F#中关键字“in”的含义

这些似乎都不是相同的用法。唯一似乎合适的是,这是一个流水线构造。

4

2 回答 2

8

let x = ... in expr允许你为一些变量声明一个绑定,然后x可以在 expr 中使用。

在这种情况下p,是一个函数,它接受一个参数stream,然后根据匹配结果返回Success或返回,该函数由函数返回。FailureCharParser

F# light 语法自动嵌套let .. in绑定,例如

let x = 1
let y = x + 2
y * z

是相同的

let x = 1 in
let y = x + 2 in
y * z

因此,in这里不需要,函数可以简单地写成

let CharParser (c: char) : Parser<char> =
    let p stream =
        match stream with
        | x::xs when x = c -> Success(x, xs)
        | _ -> Failure
    p
于 2013-03-31T09:58:55.503 回答
8

Lee的回答解释了这个问题。在 F# 中,in关键字是从早期启发 F# 并需要它的函数式语言的遗产——即来自 ML 和 OCaml。

可能值得补充的是,在 F# 中只有一种情况您仍然需要in- 即,当您想要在单行let上编写后跟表达式时。例如:

let a = 10
if (let x = a * a in x = 100) then printfn "Ok"

这是一种有点时髦的编码风格,我通常不会使用它,但in如果你想这样写,你确实需要。不过,您始终可以将其拆分为多行:

let a = 10
if ( let x = a * a
     x = 100 ) then printfn "Ok"
于 2013-03-31T11:40:57.823 回答