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

问题描述:

我发现书中Expert F# 4.0, Fourth Edition以下,由Don赛姆,亚当Granicz和安东尼奥奇斯泰尼诺:这个定义为什么会返回一个函数?

let generateStamp = 
    let mutable count = 0 
    (fun() -> count <- count + 1; count) 

我不明白为什么这个代码创建了一个功能:

val generateStamp : (unit -> int) 

它看起来我喜欢它的签名应该是

val generateStamp : int 

例如,下面的代码:

let gS = 
    let mutable count = 0 
    (printfn "%d" count; count) 

创建一个int值:

val gS : int = 0 

据我了解它的代码(fun() -> count <- count + 1; count)应首先评估拉姆达然后count。所以generateStamp的值应该只是count,因为它在gS的定义中。我错过了什么?

+4

'fun x - > y'是一个函数文字 - 它创建一个新的函数,但不评估它。在你的代码中,新创建的函数是返回值,所以你看到'generateStamp'的值与创建的函数具有相同的类型。 – Yawar

+0

@Yawar - 你可能是对的,但我不明白为什么新创建的函数是返回值。为什么返回值不是一个int,因为'count'是最后一个要评估的事物,F#没有'return'关键字,总是返回最后一个评估的事物? – Soldalma

+0

看到这个了不起的答案http://*.com/a/42430195/20371 – Yawar

在任何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进行小心替换。所以gS的值是count,而generateStamp的值是返回count的函数。

+0

很难选择两个非常明确的答案。我必须选择一个。一种观察:代码在括号之间的整个lambda体上更清晰:fun() - >(count Soldalma

这是句法诡计。最后的; count部分实际上是部分的lambda,而不是其后的下一个表达式。

这里有一些简化的例子合作,通过:

let x = 1; 2; 3  // x = 3 

let f x = 1; 2; 3 // f is a function 
let y = f 5   // y = 3, result of calling function "f" 

let f = fun x -> 1; 2; 3 // Equivalent to the previous definition of "f" 
let y = f 5    // y = 3, same as above 

let f = 
    fun x -> 1; 2; 3  // Still equivalent 
let y = f 5    // y = 3, same as above 

let f = 
    let z = 5 
    fun x -> 1; 2; 3  // Still equivalent 
let y = f 5    // y = 3, same as above 

// Your original example. See the similarity? 
let generateStamp = 
    let mutable count = 0 
    fun() -> count <- count + 1; count 

现在,如果你想有countgenerateStamp的返回值,你需要把它要么外面的括号或在下line:

// The following two definitions will make "generateStamp" have type "int" 
let generateStamp = 
    let mutable count = 0 
    (fun() -> count <- count + 1); count 

let generateStamp = 
    let mutable count = 0 
    (fun() -> count <- count + 1) 
    count