|
分類:[.NET 全般]
現在、.NET4のSystem.Linq.Expression名前空間を利用して軽量言語を作成しています。
その際、末尾再帰最適化を行いたいと考え、tailCall引数をtrueにして試したところ、
falseの時と同様に、StackOverFlowが発生してしまいました。
どのようにLambdaExpressionを作ればよいかご教示ください。
例:
-- 末尾再帰が最適化されるF#
let rec add a b = if a <= 0 then b else add (a-1) (b+1);;
let result = add 1000000 1000000;;
-- C#で動かないコード
var a = Expression.Parameter(typeof(int), "a");
var b = Expression.Parameter(typeof(int), "b");
var add = Expression.Parameter(typeof(Func<int, int, int>), "add");
var lambda = Expression.Lambda(
Expression.Condition(
Expression.LessThanOrEqual(a, Expression.Constant(0)),
b,
Expression.Invoke(add,
Expression.Subtract(a, Expression.Constant(1)),
Expression.Add(b, Expression.Constant(1)))),
true, // ← 末尾再帰を指定
a, b);
var provider = Expression.Lambda<Func<Func<int, int, int>>>(
Expression.Block(new[] { add }, Expression.Assign(add, lambda)));
var addFunc = provider.Compile().Invoke();
Console.WriteLine(addFunc(1000000, 1000000)); // StackOverFlowが発生する。
|