Calc クラスの RepeatGenerator と、それに必要な関数を書き直しました。
private static Func<Exp, Exp> GetNextDecimalDigitAndNumbers = (Exp numbers) => { Exp n0 = Exp.Number(0); Exp n1 = Exp.Number(1); Exp n2 = Exp.Number(2); Exp n9 = Exp.Number(9); Exp n10 = Exp.Number(10); return new ExpBlock { Exp.Let(new NameList{ "number", "square_difference", "scale"}, numbers), Exp.Define("maxdd", new NameList{"dd"}, Exp.If( Exp.Func(">=", Exp.Name("dd"), n0), new ExpBlock { Exp.Let("zd", Exp.Func("*", Exp.Name("dd"), Exp.Func("^", n10, Exp.Func("u-", Exp.Name("scale"))))), Exp.Let("number_sq_diff", Exp.Func("+", Exp.Func("*", Exp.Func("*", Exp.Name("number"), Exp.Name("zd")), n2), Exp.Func("*", Exp.Name("zd"), Exp.Name("zd")) )), Exp.If( Exp.Func("<=", Exp.Name("number_sq_diff"), Exp.Name("square_difference")), Exp.List(Exp.Name("dd"), new ExpList { Exp.Func("+", Exp.Name("number"), Exp.Name("zd")), Exp.Func("-", Exp.Name("square_difference"), Exp.Name("number_sq_diff")), Exp.Func("+", Exp.Name("scale"), n1) }), Exp.Func("maxdd", Exp.Func("-", Exp.Name("dd"), n1)) ) }, Exp.List(n0, Exp.List(n0, n0, n0)) )), Exp.Func("maxdd", n9) }.ExpEval(new Env()); }; public static Func<Exp> GenerateDecimal = () => new ExpBlock { Exp.Let("nums", new ExpList { Exp.Number(0), Exp.Number(3), Exp.Number(0) }), Exp.Let("current_digit", Exp.Number(0)), Exp.Define("next", new NameList { }, new ExpBlock { Exp.Subst(new NameList{ "current_digit", "nums"}, Exp.Func("GetNextDecimalDigitAndNumbers", Exp.Name("nums"))), Exp.Bool(true), }), Exp.Define("getCurrent", new NameList { }, new ExpBlock { Exp.Name("current_digit"), }), Exp.Define("setCurrent", new NameList { "val" }, new ExpBlock { }), new ExpList { Exp.Name("next"), Exp.Name("getCurrent"), Exp.Name("setCurrent") } }.ExpEval(new Env("GetNextDecimalDigitAndNumbers", Exp.FuncExpExp(GetNextDecimalDigitAndNumbers))); public static Func<string> RepeatGenerator = () => new ExpBlock { Exp.Let("generator", Exp.Func("GenerateDecimal")), Exp.Define("GetNextDecimalDigit", new NameList{}, new ExpBlock{ Exp.Func(Exp.Func(".", Exp.Name("generator"),Exp.Name("next")), new ExpList{}), Exp.Func(Exp.Func(".", Exp.Name("generator"),Exp.Name("getCurrent")), new ExpList{}), }), Exp.Define("repeat", new NameList{"number","e","count" }, Exp.If(Exp.From("e < count"), Exp.Func("repeat", Exp.Func("+", Exp.Name("number"), Exp.Func("*", Exp.Func("GetNextDecimalDigit"), 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), "GenerateDecimal", Exp.FuncExp(GenerateDecimal))).Print();
以下の構文を追加しました。
( 式, 式, … , 式 )
式のリストを表します。
Exp.Let ( 変数名, 変数名, … , 変数名 ) = 式のリスト
複数の変数に式のリストの各要素の値を代入します。文字列バージョンは以下のようになります。
let ( 変数名, 変数名, … , 変数名 ) = 式のリスト
Exp.Subst ( 変数名, 変数名, … , 変数名 ) = 式のリスト
複数のすでに存在する変数に式のリストの各要素の値を代入します。文字列バージョンは以下のようになります。