2011-10-26 6 views
2

私はF#を学ぶのに最適だと思った素早いプロジェクトを見つけました。しかし、私はちょうど何らかの理由で脳の周りを包むことができません。数時間のチュートリアルや映画までしても、私はまだ...それを手に入れません。F#は私の脳を痛めます...誰でもC#をF#に翻訳できるのですか?

Enterprise Managerの「Generate Scripts」を使用して、ストアドプロシージャのバージョン管理を開始し、スクリプトの日付を空白にしたいと考えました。私はあきらめてC#でやったけど、今は本当に好奇心が強いし、いくつかの洞察を望んでいる。

私はここに私のC#コードで、利き完全に空ではない午前:F#でいくつかのクールな探して2-3ラインのソリューションがあり、私は推測してい

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); 
} 

...私はそれを見てみたいです。

ヒントのThx!私は視覚的比較を潜在的により啓発的にするために、以下で行われていることと一致するようにそれを更新しました。また以下の素晴らしいコメント。

+6

私はそのような質問に報いるべきではないと知っていますが、私のユーモアセンスは良いコミュニティメンバーシップの意味を覆しているので、「F#は私の脳を傷つけます。 – David

+0

F#をC#に戻しました。 – gradbot

+0

LOL ...ええ、ハァッ。 :)実際には、私は、ポイントを説明するのを助けるために、元のforeachループの本体にかなり適切な.NET呼び出しを戻しています。 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)) 

注意(EDIT:だった)もはるかに冗長必要以上。

+0

それは信じられないほど短いです... – Wojteq

+2

'Seq.iter'の代わりに' for'を使ってもう一つの行を保存することができますなぜ組み込みの言語構造がある場合にライブラリ関数を使うのですか? –

+1

@Tomas: - 私は避けることができるときにF#で必須の構造体を使用するのが好きではありませんし、 'Directory.EnumerateFiles'の呼び出しと同じ行に' Seq.iter'を置くことで1行を節約することもできます; - ] – ildjarn

1

トリビアル。コンパイル。リフレクターで開きます。 F#への逆コンパイラ言語を選択してください。

+0

これは簡単すぎます。 ;-) – David

+2

さらに、それはあなたに慣用的または代表的なF#コードを与えることはまともなチャンスがあります。 – delnan

+4

あなたは冗談か? ReflectorのF#サポートは非​​常にバグです。ほとんどすべての方法でクラッシュします。 – Daniel

5

はかなりあなたがする必要があるすべては(あなたがC#でvarを書くことができます)、letキーワードと変数の宣言で型名を置き換え、すべてのセミコロンや中括弧を削除し、
for file in files doforeachを交換することです。 F#で、あなたのような何かを必要とするので、あなたはまた、いくつかの名前空間を使用している:

open System.IO 
open System.Text.RegularExpressions 

をあなたは1つの不定変数(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) 

この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の終わりにループの繰り返し(この場合)。あなたのC#コードある

+0

答えていただきありがとうございます。C#ステートメントをF#ステートメントに直接移植する方法を知ることは間違いありませんildjarnの答えは "F#way"の仕組みを実際に示しましたが、 1 – user1015250

関連する問題