ラムダ式で再帰表現を書いてみました
こんにちは、こだかです。
今回は、さあできること開発者セミナーのツアー中で出た話題
「ラムダ式で再帰表現を書いてみよう!」を書きたいと思います。
ラムダ式の元は関数言語からきていますので、考え方としては、再起表現はぴったり当てはまります。
例えば、指定された整数の和(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#でもっと良い方法があったらフィードバックお願いします。
こだかたろう
Comments
Anonymous
June 11, 2008
The comment has been removedAnonymous
June 13, 2008
ラムダ式で再帰、待っておりました。 なるほど、変数(関数のリファレンス)を先に用意しておいて、この変数を参照する形でラムダ式を定義することで、結果、再帰の輪が完成するわけですね。 ラムダ式で再帰、どうやってやるんだろう? とずっと考えておりましたが、これでスッキリです。Anonymous
June 15, 2008
The comment has been removed