Action<T>を使い倒してみる(つづき)
・・・ということでさっそく作ってみた。nが増えるにつれ素晴らしいモノが出力される。念のためにx100をコンパイルしてみてtestと表示できることを確認済み。
using System; namespace garu.ActionN { static class ActionN { const int TAB = 2; const string TYPE0 = "string"; const string VALUE0 = "\"test\""; const string VALUE1 = "Console.WriteLine"; static string Type(int n) { if (n == 0) return TYPE0; return "Action<" + Type(n - 1) + ">"; } static string Tab(int p) { return new string(' ', p * TAB); } static string Value(int n, int p) { if (n == 0) return VALUE0; if (n == 1) return VALUE1; string pn = string.Format("p{0}", p + 1); return "delegate(" + Type(n - 1) + " " + pn + ")\n" + Tab(p) + "{\n" + Tab(p + 1) + pn + "(" + Value(n - 2, p + 1) + ");\n" + Tab(p) + "}"; } static void Main(string[] args) { for (int n = 1; n < 20; n++) { string xn = string.Format("x{0}", n); Console.WriteLine( Type(n) + " " + xn + " =\n" + Value(n, 0) + ";\n" + xn + "(" + Value(n - 1, 0) + ");"); } } } }
雑に書いた仕様書も置いとく。
メインルーチン (+で始まるところをタイプルーチンで置き換え) (-で始まるところを値ルーチンで置き換え) +[n] xn = -[n]; xn(-[n-1]); タイプルーチン n=0のとき string n>0のとき Action<+[n-1]> 値ルーチン n=0のとき "test" n=1のとき Console.Write n>1のとき (p?は値ルーチンの再帰深度で番号を増やす) (@は値ルーチンの再帰深度でタブを入れる) delegate(+[n-1] p?) @{ @@p?(-[n-2]); @}