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#でラムダ関数が使える意義ってなんなんだろうねぇ。