2010-08-24 13 views
16

這是一個非常簡單的問題,我只想檢查我正在做什麼以及我如何解釋F#是否合理。如果我有聲明F#函數與值的對比

let printRandom = 
    x = MyApplication.getRandom() 
    printfn "%d" x 
    x 

而不是創建printRandom作爲函數,F#運行它一次,然後給它分配一個值。所以,現在,當我打電話給printRandom,而不是獲得一個新的隨機值並打印它時,我只是得到了第一次返回的內容。我可以解決這個問題我將其定義爲這樣的:

let printRandom() = 
    x = MyApplication.getRandom() 
    printfn "%d" x 
    x 

這是繪製無參數的功能和價值之間的區別的正確方法?這對我來說似乎不太理想。它在咖喱,成分等方面有後果嗎?

+2

請注意,您幾乎可以肯定地想要在第一次出現「x」前添加'let',否則您正在執行比較,然後丟棄結果。 – kvb 2010-08-24 16:36:43

+0

真棒問題,有*確切*相同的問題。不幸的是我發現了這個解決方案後發現了這個。 – ses011 2012-09-06 01:47:44

回答

18

看這個的正確方法是F#沒有無參數函數之類的東西。所有函數都需要一個參數,但有時你不在乎它是什麼,所以你使用()(單元類型的單例值)。你也可以做這樣的功能:

let printRandom unused = 
    x = MyApplication.getRandom() 
    printfn "%d" x 
    x 

或本:

let printRandom _ = 
    x = MyApplication.getRandom() 
    printfn "%d" x 
    x 

()是默認的方式來表達,你不使用該參數。它向來電者表達了這個事實,因爲這種類型是unit -> int而不是'a -> int;以及讀者,因爲呼叫站點是printRandom()而不是printRandom "unused"

Currying和組合實際上依賴於所有函數都帶一個參數並返回一個值的事實。

順便說一句,用單元編寫調用的最常見方式是使用空格,特別是在像FIM的非.NET親戚中,例如Caml,SML和Haskell。這是因爲()是一個單例值,而不是它在C#中的語法。

8

你的分析是正確的。

第一個實例定義了一個值而不是函數。我承認,當我開始使用F#時,這讓我感到有些困惑。來自C#看起來非常自然,包含多個語句的賦值表達式必須是lambda表達式,因此延遲評估。

F#中的情況並非如此。語句幾乎可以任意嵌套(並且它具有局部範圍的函數和值)。一旦你對此感到滿意,你可以開始看到它是一個優勢,因爲你可以創建函數的其餘部分無法訪問的函數和延續。

第二種方法是創建邏輯上不帶參數的函數的標準方法。我不知道F#團隊在這個聲明中使用的確切術語(可能是一個採用unit類型的單個參數的函數)。所以我不能評論它會如何影響咖喱。

+4

因爲函數只有一個'unit'類型的參數,所以Currying並不適用。部分應用程序沒有意義:您要麼完全應用該函數(傳遞'()'),要麼完全不調用它。 – 2010-08-24 09:01:01

7

這是繪製參數少 功能和價值之間的區別 適當的方式?這對我來說似乎不是理想的 。它有 在咖喱,成分, 等的後果?

是的,你所描述的是正確的。

對於它的價值,它有一個非常有趣的結果,能夠部分評估聲明函數。比較這兩個功能:

// val contains : string -> bool 
let contains = 
    let people = set ["Juliet"; "Joe"; "Bob"; "Jack"] 
    fun person -> people.Contains(person) 

// val contains2 : string -> bool 
let contains2 person = 
    let people = set ["Juliet"; "Joe"; "Bob"; "Jack"] 
    people.Contains(person) 

兩個函數產生相同的結果,contains創造它的人對申報設置並重新使用它,而contains2創造它的人設置每次調用該函數。最終結果:contains稍快。所以瞭解這裏的區別可以幫助您編寫更快的代碼。

3

看起來像函數體的賦值機構只有少數程序員不知道。您可以通過具有分配回報的功能讓事情更有趣:

let foo = 
    printfn "This runs at startup" 
    (fun() -> printfn "This runs every time you call foo()") 

我剛剛寫了一篇博客帖子大約是在http://blog.wezeku.com/2010/08/23/values-functions-and-a-bit-of-both/