为什么这个定义会返回一个函数?

Sol*_*lma 3 f#

我在Expert F# 4.0, Fourth EditionDon Syme,Adam Granicz和Antonio Cisternino 的书中找到了以下内容:

let generateStamp =
    let mutable count = 0
    (fun () -> count <- count + 1; count)
Run Code Online (Sandbox Code Playgroud)

我无法理解为什么这段代码会创建一个函数:

val generateStamp : (unit -> int)
Run Code Online (Sandbox Code Playgroud)

它看起来像它的签名应该是

val generateStamp : int
Run Code Online (Sandbox Code Playgroud)

例如,以下代码:

let gS =
    let mutable count = 0
    (printfn "%d" count; count)
Run Code Online (Sandbox Code Playgroud)

创建一个int值:

val gS : int = 0
Run Code Online (Sandbox Code Playgroud)

据我所知,代码(fun () -> count <- count + 1; count)应首先评估lambda然后count.所以它的价值generateStamp应该是正确的count,因为它在定义中gS.我错过了什么?

rmu*_*unn 5

在任何F#代码块中,该块中的最后一个表达式将是该块的值.块可以用两种方式之一定义:缩进,或;块的表达式之间.

表达式fun () -> other expressions here创建一个函数.因为这是代码块中的最后一个表达式let generateStamp =,这是存储的值generateStamp.

您的困惑在于您认为其中的表达式fun ()将作为值的一部分立即进行评估generateStamp,但它们不是.它们定义了表达式返回的匿名函数的主体fun ().你完全正确的是在那个代码块里面,count是最后一个表达式,所以它是由该函数返回的东西.但该fun ()表达式创建了一个函数,该函数仅在以后调用时才评估其内容.它不会立即评估其内容.

相比之下,表达式(printfn "%d" count; count)是一个代码块,其中包含两个表达式.它不是一个函数,因此将立即进行评估.它的最后一个表达式是count,所以代码块的值(printfn "%d" count; count)count.由于(printfn "%d" count; count)正在对块进行立即评估,因此您可以在心理上将其替换为count.所以值gScount,而值generateStamp是一个在评估时会返回 的函数count.