C#4.0でラムダ関数を使ってみる。
しょーもないプログラムです。こんなことができるんだ〜程度のお話。
ニコ生放送みてたらこんなプログラムが出てきた。
Clojureで書いたら〜。ってのも芸が無いので、C#4.0のラムダ関数と無名型で書いてみた。
// C# 4.0 using System; namespace RocketLauncher { class Program { static void Main(string[] args) { // 「2つのラムダ関数をメンバに持つ無名型オブジェクト」 // を返すラムダ関数(ややこしいな)。 // ラムダ関数を無名型のメンバにすると型推論されずエラーになる。 // ただしキャストすればOK。 Func<int, int, dynamic> factory = (id, count) => new { next = (Func<int>)(() => count--), display = (Func<string>)(() => count > 0 ? string.Format("[No.{0} Count:{1}]", id, count) : count == 0 ? string.Format("[{0}番ロケット発射!]", id) : string.Format("[{0}番ロケットは既に発射されました]", id)) }; var rocket1 = factory(1, 3); var rocket2 = factory(2, 7); var rocket3 = factory(3, 5); var nx1 = rocket1.next; var nx2 = rocket2.next; var nx3 = rocket3.next; var disp1 = rocket1.display; var disp2 = rocket2.display; var disp3 = rocket3.display; Func<bool> isFinished = () => { // & でビット積をとるのはnx1, nx2, nx3 をすべて評価させるため。 // && で判定してしまうと、((nx1()<=0)&&(nx2()<=0)) == false //となった時点で評価が完了し、nx3が実行されない。それだと困る。 Func<Func<int>, int> chk = (nx) => (nx() <= 0 ? 1 : 0); return 1 == (chk(nx1) & chk(nx2) & chk(nx3)); }; Func<string> joinDisp = () => disp1() + disp2() + disp3(); // ラムダ関数の再帰でループ。意味もなく末尾再帰。 Func<bool> loop = null; (loop = () => { if (isFinished()) return true; Console.WriteLine(joinDisp()); return loop(); })(); } } }
出力
[No.1 Count:2][No.2 Count:6][No.3 Count:4] [No.1 Count:1][No.2 Count:5][No.3 Count:3] [1番ロケット発射!][No.2 Count:4][No.3 Count:2] [1番ロケットは既に発射されました][No.2 Count:3][No.3 Count:1] [1番ロケットは既に発射されました][No.2 Count:2][3番ロケット発射!] [1番ロケットは既に発射されました][No.2 Count:1][3番ロケットは既に発射されました] [1番ロケットは既に発射されました][2番ロケット発射!][3番ロケットは既に発射されました]
C#でラムダ関数が使える意義ってなんなんだろうねぇ。