2012-08-01 86 views
7

我注意到靜態方法在F#中比C#更受歡迎。在C#中,你總是一個元素通過調用一個實例方法添加到集合:F#編碼風格 - 靜態與實例方法

mySet.Add(elem); 

但在F#通常存在等效靜態方法:

mySet.Add(elem) 
// OR 
Set.Add elem mySet 

我也看到了後者在樣本中經常出現。在我看來,在語義上和功能上完全相同,但是來自C#背景,使用實例方法感覺更自然。 F#中哪種風格更好?爲什麼?

+0

相關:http://stackoverflow.com/q/7698133/162396 – Daniel 2012-08-01 19:24:03

+0

移動回答。 – 2012-08-01 19:40:46

+0

有許多原因,根源在於函數式編程作爲一個整體,對於F#來說有一些特殊之處,很難知道從哪裏開始進行驗證。一旦你熟悉函數式編程,它就會變得很明顯。 – Daniel 2012-08-01 21:27:53

回答

8

除了與類型推斷相關的答案中提到的原因之外,在功能樣式中更自然地發送函數作爲參數。 如果它是一個實例方法,你將不得不寫這樣的事:

myHigherOrderFunction (fun (x:MyType) -> x.myFunctionAsMethod) 

但如果它被定義爲一個靜態方法,你可以這樣寫:

myHigherOrderFunction MyType.myFunctionAsMethod 

這是更優雅,更容易寫(讀取也是如此),並且與發送常規允許函數時的語法幾乎相同。

一個實例方法需要一個類型的實例才能訪問函數(方法),在OOP中,這不是一個問題,因爲您認爲在發送消息給對象但在FP中,函數單獨(沒有實例)是一等公民。

要訪問一個靜態方法,你需要指定Class,你可以將Class看作一種具有函數的容器(如模塊或命名空間)。

+0

fp風格的優秀用例。在編程風格上,實例功能更短。 – nicolas 2012-08-04 13:51:14

0

在f#中,作爲函數式語言的更原生的分離變量是不可變的,而函數是操作。這個功能類似於c#中的靜態方法,但是對於c#方法,函數有一個優點。這是部分應用。您可以傳遞一些(而不是全部)參數的功能,並且這個函數的一部分參數將成爲需要其他參數的新函數。

5

大多數標準F#類型是不可變的。當使用不可變對象的工作,靜態方法更好的刻畫是怎麼回事,比如:

mySet.Add(elem); 

貌似mySet突變爲包括elem,當F#集將返回一個新的mySet。幸運的是F#未能編譯以確保你不犯這個錯誤,它仍然導致代碼混淆。相反:

mySet |> Set.Add elm 

在形式上是截然不同的,看起來它會返回一些新的東西,而不會離原本太遠。

2

儘管F#中的靜態方法非常常見,但我發現實例方法對組件開發有很大意義。

原因? F#模塊系統缺少函子。在其他類型的ML中,如SML或OCaml,您可以將組件作爲簡單模塊進行開發。如果您稍後決定參數化模塊,則可以將其提升爲仿函數,而不必重寫太多的源代碼。在F#中你不能。

要在F#中創建一個參數化的「模塊」,您必須求助於一個類並將您的方法轉換爲實例方法,並在實例構建期間傳入參數。不幸的是,從一個模塊到一個類涉及很多機械但令人討厭的源代碼更改。因此,硬核組件程序員可能會選擇默認使用類和實例方法,就像在C#中一樣。這讓人聯想到SML中有時採用的「只有函子式」風格。