2017-02-24 146 views
3

我發現書中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://stackoverflow.com/a/42430195/20371 – Yawar

回答

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進行小心替換。所以gS的值是count,而generateStamp的值是返回count的函數。

+0

很難選擇兩個非常明確的答案。我必須選擇一個。一種觀察:代碼在括號之間的整個lambda體上更清晰:fun() - >(count < - count + 1; count)'。另一方面,在這行代碼或原始版本的函數中不需要括號。 – Soldalma

3

這是句法詭計。最後的; 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 
相關問題