Calc クラスの IterateGenerator と RepeatServer です。
public static Func<string> IterateGenerator = () => new ExpBlock { Exp.Define("take", new NameList{"count", "gen"}, Exp.If( Exp.Func("==", Exp.Name("count"), Exp.Number(0)), Exp.Nil(), new ExpBlock { Exp.Let(new NameList{"next", "getCurrent", "setCurrent"}, Exp.Name("gen")), Exp.If(Exp.Func("next"), Exp.Cons( Exp.Func("getCurrent"), Exp.Func("take", Exp.Func("-", Exp.Name("count"), Exp.Number(1)), Exp.Name("gen")) ), Exp.Nil()) } ) ), Exp.Define("zipn", new NameList{"f", "n", "list"}, Exp.If( Exp.Func("null", Exp.Name("list")), Exp.Nil(), Exp.Cons( Exp.Func(Exp.Name("f"), Exp.Func("first", Exp.Name("list")), Exp.Name("n")), Exp.Func("zipn", Exp.Name("f"), Exp.Func("+", Exp.Name("n"), Exp.Number(1)), Exp.Func("tail", Exp.Name("list"))) ) ) ), Exp.Define("nlist", new NameList{"list"}, Exp.Func("zipn", Exp.Fun(new NameList{"n", "e"}, Exp.Func("*", Exp.Name("n"), Exp.Func("^", Exp.Number(10), Exp.Func("u-", Exp.Name("e")) ) ) ), Exp.Number(0), Exp.Name("list"))), Exp.Define("foldr", new NameList{"f", "n", "list"}, Exp.If( Exp.Func("null", Exp.Name("list")), Exp.Name("n"), Exp.Func(Exp.Name("f"), Exp.Func("first", Exp.Name("list")), Exp.Func("foldr", Exp.Name("f"), Exp.Name("n"), Exp.Func("tail", Exp.Name("list"))) ) ) ), Exp.Define("number", new NameList{"list"}, Exp.Func("foldr", Exp.Fun(new NameList{"x", "y"}, Exp.Func("+", Exp.Name("x"), Exp.Name("y"))), Exp.Number(0), Exp.Func("nlist", Exp.Name("list")))), Exp.Func("number", Exp.Func("take", Exp.Name("count"), Exp.Func("GenerateDecimal")) ) }.ExpEval(new Env("count", Exp.Number(count), "GenerateDecimal", Exp.FuncExp(GenerateDecimal))).Print(); public static Func<string> RepeatServer = () => new ExpBlock { Exp.Let("numbers", new ExpList { Exp.Number(0), Exp.Number(3), Exp.Number(0) }), Exp.Define("repeat", new NameList{"number","e","count" }, Exp.If(Exp.From("e < count"), new ExpBlock{ Exp.Let(new NameList{"dd", "ns"}, Exp.Func("GetNextDecimalDigitAndNumbers", Exp.Name("numbers"))), Exp.Subst("numbers", Exp.Name("ns")), Exp.Func("repeat", Exp.Func("+", Exp.Name("number"), Exp.Func("*", Exp.Name("dd"), Exp.Func("^", Exp.Number(10), Exp.Func("u-", Exp.Name("e"))) ) ), Exp.Func("+", Exp.Name("e"), Exp.Number(1)), Exp.Name("count")), }, Exp.Name("number")) ), Exp.Func("repeat", new ExpList{Exp.Number(0), Exp.Number(0) , Exp.Name("count") }) }.ExpEval(new Env("count", Exp.Number(count), "GetNextDecimalDigitAndNumbers", Exp.FuncExpExp(GetNextDecimalDigitAndNumbers))).Print();
上記の文字列版です。
public static Func<string> IterateGenerator = () => Exp.From("{" + "def take (count, gen) = " + "if count == 0 then " + "nil " + "else { " + "let (next, getCurrent, setCurrent) = gen; " + "if next() then " + "cons(getCurrent(), take(count - 1, gen)) " + "else " + "nil " + "}; " + "def zipn (f, n, list) = " + "if null(list) then " + "nil " + "else " + "cons(f(first(list), n), zipn(f, n + 1, tail(list))); " + "def nlist (list) = " + "zipn(fun(n, e) = n * 10^(-e), 0, list);" + "def foldr (f, n, list) = " + "if null(list) then " + "n " + "else " + "f(first(list), foldr(f, n, tail(list))); " + "def number (list) = " + "foldr(fun (x, y) = x + y, 0, nlist(list)); " + "number(take(count, GenerateDecimal())) " + "}").ExpEval(new Env("count", Exp.Number(count), "GenerateDecimal", Exp.FuncExp(GenerateDecimal))).Print(); public static Func<string> RepeatServer = () => Exp.From("{" + "let numbers = (0, 3, 0);" + "def repeat(number, e, count) = " + "if e < count then { " + "let (dd, ns) = GetNextDecimalDigitAndNumbers(numbers);" + "subst numbers = ns;" + "repeat(number + dd * 10^(-e), e + 1, count) " + "} else " + "number;" + "repeat(0, 0, count)" + "}").ExpEval(new Env("count", Exp.Number(count), "GetNextDecimalDigitAndNumbers", Exp.FuncExpExp(GetNextDecimalDigitAndNumbers))).Print();
無名関数の構文を追加しました。
Exp.Fun ( new NameList { 変数名, 変数名, … , 変数名 }, 式 )
無名関数を表します。