2011-10-26 59 views
2

我發現了一個快速的項目,我認爲將是完美的學習F#。然而,出於某種原因,我無法將我的大腦包裹在它周圍。幾小時的教程,甚至一些電影,我仍然只是...不明白。F#傷害了我的大腦......任何人都可以幫助翻譯C#到F#嗎?

,所以我想使用Enterprise Manager「生成腳本」開始我們的版本在工作中的存儲過程,想空出的腳本日期。我放棄了並用C#做了它,但現在我真的很好奇,希望得到一些見解。

我不完全是兩手空空,這是我的C#代碼:

string path = @"C:\Subversion\CompanyName\SQL\DBName"; 
string fileSpec = "*.sql"; 
string pattern = @"Script Date: \d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}"; 
string replace = "Script Date: "; 

foreach (var file in Directory.EnumerateFiles(path, fileSpec)) 
{ 
    string content = File.ReadAllText(file); 

    content = Regex.Replace(content, pattern, replace); 

    File.WriteAllText(file, content, Encoding.Unicode); 
} 

我猜有F#中一些很酷的2-3線解決方案...我很想看到它。

THX的提示!我已經對它進行了更新以匹配下面正在做的事情,以使視覺比較更具啓發性。下面還有很棒的評論。

+6

我知道我不應該回報這樣一個問題,但我的幽默感正在壓倒我良好的社區成員感,所以+1爲「F#傷害了我的大腦」。 – David

+0

將F#翻譯回C#。 – gradbot

+0

大聲笑...是的,呵呵。 :)實際上,我將相當適合的.NET調用翻譯成原始foreach循環的主體,以幫助說明這一點。 ildjarn建議我注意。我注意到。 ;) – user1015250

回答

10
let path = @"C:\Subversion\CompanyName\SQL\DBName" 
let fileSpec = "*.sql" 
let pattern = @"Script Date: \d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}" 
let replace = "Script Date: " 

Directory.EnumerateFiles (path, fileSpec) 
|> Seq.iter (fun file -> 
    let content = Regex.Replace (File.ReadAllText file, pattern, replace) 
    File.WriteAllText (file, content, Encoding.Unicode)) 

請注意,您的C#代碼編輯:是)也遠遠超過必要的繁瑣。

+0

這是令人難以置信的短... – Wojteq

+2

您可以使用'for'而不是'Seq.iter'保存多一行爲什麼在內置語言結構時使用庫函數? –

+1

@Tomas:個人偏好 - - 我不喜歡在F#中使用命令式結構,當我可以避免時,我也可以通過將'Seq.iter'放在與Directory.EnumerateFiles調用相同的行上來保存一行[ – ildjarn

1

微不足道。編譯。在反射器中打開。選擇反編譯器語言爲F#。

+0

這太容易了。 ;-) – David

+2

此外,有一個很好的機會,它不會給你慣用的或代表性的F#代碼。 – delnan

+4

你在開玩笑嗎?反射器的F#支持是令人難以置信的錯誤 - 幾乎每種方法都會崩潰。 – Daniel

5

幾乎所有你需要做的就是在變量聲明與let關鍵字替換類型名稱(在那裏你可以在C#編寫var),刪除所有分號和花括號,並與
for file in files do更換foreach。您還使用了一些命名空間,所以在F#中,你需要的東西,如:

open System.IO 
open System.Text.RegularExpressions 

您使用一個可變變量(content),但你並不真的需要它發生變異。你可以使用不同的變量(如newContent)到店置換的結果。因此,中間部分將是:

let content = File.ReadAllText(file) // No need for a stream reader here! 

let pattern = @"Script Date: \d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}" 
let replace = "Script Date: "  
let newContent = Regex.Replace(content, pattern, replace) 

您也可以使用相同的變量名,這意味着你宣佈一個新的(immutable)的變量,它隱藏了前一個在範圍的其餘部分(見這SO answer for more information

我也會改變的最後一位(甚至在C#!)關閉,即使發生異常流。在C#中,您可以使用using。寫在F#同樣的事情,你可以使用use關鍵字:

use fileStream = new FileStream(file, FileMode.Truncate, FileAccess.Write, FileShare.None) 
use writer = new StreamWriter(fileStream, Encoding.Unicode) 
writer.Write(content) 
writer.Flush() 

use關鍵字保證了對象佈置(關閉),當它超出範圍 - 即,在for結束循環迭代(在這種情況下)。

+0

感謝您的回答,看看C#語句如何直接移植到F#語句中是非常有用的,ildjarn的答案真正顯示了它是如何完成的「F#方式」,但是感謝您的評論以及上述評論fwiw + 1 – user1015250

相關問題