[英]Why do ML languages (F#) have so many different operators compared to C languages (C#)?
[英]F#: Why do I have to explicitly specify 'unit' for functions taking no arguments?
所以我剛剛完成了我的第一個F#程序,我唯一的功能背景是對Haskell 的一點知識(讀:沒有真正生成任何程序)。
在經歷了一些令人難以置信的行為后,我開始意識到F#區分了:
prepareDeck = allSuits |> List.collect generateCards |> shuffle
和
prepareDeck() = allSuits |> List.collect generateCards |> shuffle
我注意到它“緩存”了前者,如果再次調用則不會重新計算它,而它將后者視為正常函數。 如果有問題的功能沒有副作用,你無法區分,顯然,但是我的shuffle
了!
這應該是常識嗎? 我還沒有在任何教程材料上看到它。 原因只是解析器中的一個弱點,有點像你在使用它之前必須聲明一個函數?
大多數F#材料確實解釋了模塊中的所有頂級語句都是從聲明自上而下執行的。 換句話說,您聲明的不是函數,而是程序運行時綁定一次的值。
查看反映的代碼確實很有幫助。 我有一個簡單的文件:
let juliet = "awesome"
let juliet2() = "awesome"
編譯后的代碼如下所示:
public static string juliet
{
[CompilerGenerated, DebuggerNonUserCode]
get
{
return "awesome";
}
}
//...
public static string juliet2()
{
return "awesome";
}
所以一個是靜態屬性,另一個是函數。 這是一個理想的屬性,因為想象一下,如果我們有這樣的東西:
let x = someLongRunningDatabaseCall()
我們只希望x
綁定一次,我們不希望它每次訪問x
調用數據庫函數。
另外,我們可以編寫這樣有趣的代碼:
> let isInNebraska =
printfn "Creating cities set"
let cities = set ["Omaha"; "Bellevue"; "Lincoln"; "Papillion"; "La Vista"; "Ralston"]
fun n -> cities.Contains(n);;
Creating cities set
val isInNebraska : (string -> bool)
> isInNebraska "Omaha";;
val it : bool = true
> isInNebraska "Okaloosa";;
val it : bool = false
由於isInNebraska
是一個值,因此立即進行評估。 恰好它的數據類型是(string -> bool)
,所以它看起來像一個函數。 因此,即使我們調用函數1000次,我們也只填充一次設置的cities
。
讓我們將該代碼與此進行比較:
> let isInNebraska2 n =
printfn "Creating cities set"
let cities = set ["Omaha"; "Bellevue"; "Lincoln"; "Papillion"; "La Vista"; "Ralston"]
cities.Contains(n);;
val isInNebraska2 : string -> bool
> isInNebraska2 "Omaha";;
Creating cities set
val it : bool = true
> isInNebraska2 "Okaloosa";;
Creating cities set
val it : bool = false
糟糕,我們每次調用函數時都會創建一個新的城市集。
因此,價值觀和功能之間肯定存在合理和真實的區別。
這就是幾乎每種語言都有副作用的方法。
let name = expr
運行代碼'now',如果expr
,可能會導致副作用。 對name
后續引用沒有任何效果。 而
let name() = expr
定義一個函數,現在沒有效果,並且每次調用name()
時都會評估(並產生效果)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.