大多數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
哎呀,我們創建設定每次我們調用功能的新城市。
所以肯定是價值和功能之間的合法和真正的區別。
不錯的例子。對於任何有興趣的人來說,「Expert F#」書(第8章)在設計用於高效部分應用的功能的背景下進一步發展了這個討論。 – itowlson 2010-01-30 01:29:59
我認爲這裏存在一個缺陷:靜態屬性和靜態方法之間沒有多大區別,**都是幕後的方法**,對屬性的訪問實際上是方法調用(這就是爲什麼您可以標記屬性爲*虛擬*)。我看不到你的「理想財產」。 – 2010-02-02 00:35:45
我相信不同的是,當你有'let julietNoFunction = ...'時,靜態屬性將簡單地返回一個存儲在靜態字段中的值,並且這個值在生成類型的靜態構造函數中只計算一次模塊。我想我已經在Reflector中看到過這個,但我不確定了。無論如何,你提出的方式在使用'let juliet = ...'到'let juliet()= ...'上並沒有顯示任何優勢。 – 2010-02-02 00:46:13