我有以下程序:
let readStoriesInQAForm = 
    printfn "Inside the let!"
    0 
[<EntryPoint>]
let main argv = 
    printfn "Ah! entering point to the main!"
    System.Console.ReadKey() |> ignore
    0 // return an integer exit code
Run Code Online (Sandbox Code Playgroud)
我期望获得以下输出(因为main是入口点,并且没有函数调用):
Ah! entering point to the main!
Run Code Online (Sandbox Code Playgroud)
但是当我在VS 2013中编译并运行它时,我得到了这个:
Inside the let!
Ah! entering point to the main!
Run Code Online (Sandbox Code Playgroud)
我的错是什么?
在F#程序中,代码基本上是从上到下运行,因此以后需要的任何值都可用.
例如,如果你写了:
[<EntryPoint>]
let main argv = 
    printfn "Ah! entering point to the main!"
    printfn readStoriesInQAForm
    System.Console.ReadKey() |> ignore
    0 // return an integer exit code
Run Code Online (Sandbox Code Playgroud)
观察到的行为非常有意义,因为跳出main来计算一个常量值是不合逻辑的.
要避免此问题,您需要创建readStoriesInQAForm一个函数,如下所示:
let readStoriesInQAForm() = ...
Run Code Online (Sandbox Code Playgroud)
        正如John Palmer在他的回答中所描述的那样,F#代码从上到下执行.的let关键字结合的值,以一个名称-在这种情况下,值0被绑定到readStoriesInQAForm名称.
除了原始值,您还可以将函数绑定到名称; F#是一种函数式编程语言,因此函数也是值.如果将函数绑定到名称,则可以通过调用它来执行该函数.
但是,readStoriesInQAForm它不是一个函数 - 它是一个原始值(0),它在main被调用之前被绑定,以便使该值可用main.在这种特殊情况下,let定义绑定的方式,它在发生绑定时具有打印到标准输出的副作用.(一般来说,在功能编程中,你越能避免副作用,就越好.)
如果要避免此行为,请将let绑定从原始值更改为函数:
let readStoriesInQAForm () = 
    printfn "Inside the let!"
    0
Run Code Online (Sandbox Code Playgroud)
更好的是将名称绑定到值而没有任何副作用:
let readStoriesInQAForm = 0
Run Code Online (Sandbox Code Playgroud)