Calc クラスの RepeatGenerator をラムダ式のようなもので書き直したものの動作するバージョンです。
public static Func<string> RepeatGenerator = () => new ExpBlock { Exp.Let("generator", Exp.From("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.From("repeat(number + GetNextDecimalDigit() * 10^(-e), e + 1, count)"), Exp.From("number")) ), Exp.Func("repeat", new ExpList{Exp.Number(0), Exp.Number(0) , Exp.Name("count") }) }.ExpEval(new Env("count", Exp.Number(count), "GenerateDecimal", Exp.FuncIterator(GenerateDecimal))).Print();
文字列でも書けるようになっています。以下のようになります。
public static Func<string> RepeatGenerator_ = () => Exp.From("{ let generator = GenerateDecimal();" + "def GetNextDecimalDigit() = { generator.next(); generator.getCurrent() };" + "def repeat(number, e, count) = " + "if e < count " + "then repeat(number + GetNextDecimalDigit() * 10^(-e), e + 1, count) " + "else number;" + "repeat(0, 0, count) }" ).ExpEval(new Env("count", Exp.Number(count), "GenerateDecimal", Exp.FuncIterator(GenerateDecimal))).Print();
Exp.From ( 文字列 ) という形式で書きます。仕様は以下のようになります。
関数名 ( 引数, 引数, … , 引数 )
関数を実行します。関数名は名前または関数を表す式です。
let 変数名 = 式
変数に式の値を代入します。
subst 変数名 = 式
すでに存在する変数に式の値を代入します。
If 式(条件) then 式(真のとき) else 式(偽のとき)
「式(条件)」が真のとき「式(真のとき)」、「式(偽のとき)」が評価されます。
def 関数名 ( 変数名, 変数名, … , 変数名) = 式
関数を定義します。
{ 式; 式; … ; 式 }
式を順に実行します。
単項演算子
符号を変える ( - )
二項演算子
足し算 ( + )
引き算 ( - )
掛け算 ( * )
正の整数の割り算の商 ( / )
x と y が正の整数のとき割り算の商を求めることができます。
正の整数の割り算の余り ( % )
x と y が正の整数のとき割り算の余りを求めることができます。
累乗 ( ^ )
正の整数の正の整数乗(結果は整数の範囲)、または 10 の整数乗を求めることができます。