ラムダ式で再帰表現を書いてみました

こんにちは、こだかです。

今回は、さあできること開発者セミナーのツアー中で出た話題
「ラムダ式で再帰表現を書いてみよう!」を書きたいと思います。

ラムダ式の元は関数言語からきていますので、考え方としては、再起表現はぴったり当てはまります。

例えば、指定された整数の和(n + n-1 + n-2 +...+1)を求める関数を定義してみます。

Func<int,int> func = null;
func = x => x < 1 ? 0 : x + func(x - 1);

ちょっと見慣れないかもしれないですね。
Func<int,int>は引数と戻り値がともにintである関数funcを宣言しています。
次にfuncの実装を行っており、「funcは引数xが1より小さかったら0、そうでない場合は x + f(x-1)を計算する」ことを表現したものです。 そうして、引数xの値が0になるまで、繰り返しの計算を行います。

呼び出してみます。ためしに1から10までの和を求めてみます。

MessageBox.Show(func(10).ToString());

結果は当然55になります。何となく、ご理解頂けるでしょうか?

では、これだけだと面白くないので、今度はI/Oを伴ったモノにしてみます。
例としては、そうですねSinカーブの描画を行ってみたいとおもいます。

private void button1_Click(object sender, EventArgs e)
{
    pictureBox1.Image = null;
    Bitmap bitmap = new Bitmap(810, 300);
    double x = 0;

    Func<Bitmap, double, Bitmap> func = null;
    func = (bm, x1) => (SetPixel(bm, (int)x1, (int)(200 / 2 * (1 - (float)Math.Sin(x1 * 2 * Math.PI / (800 - 1))))) > 800) ? bm : func(bm, x1 + 1);
    pictureBox1.Image = func(bitmap, x);
}

public int SetPixel(Bitmap b, int x, int y)
{
    b.SetPixel(x, y, Color.Red);
    return x;
}

できましたけど、なんだか美しくないですね。(Sinカーブ描画用の座標位置の計算がごちゃごちゃしている点はおいたとしても、SetPixelを新たに定義しているところなんか最悪です。)
この辺関数言語なら、スッキリ治まるのですが・・・C#でもっと良い方法があったらフィードバックお願いします。

実行結果です。
 image

こだかたろう