C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: Expression.Lambda関数のtailCall引数


(過去ログ 92 を表示中)

[トピック内 3 記事 (1 - 3 表示)]  << 0 >>

■54900 / inTopicNo.1)  Expression.Lambda関数のtailCall引数
  
□投稿者/ ground (1回)-(2010/11/09(Tue) 00:22:26)

分類:[.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が発生する。

引用返信 編集キー/
■54904 / inTopicNo.2)  Re[1]: Expression.Lambda関数のtailCall引数
□投稿者/ shu (159回)-(2010/11/09(Tue) 08:07:59)
2010/11/09(Tue) 08:46:50 編集(投稿者)

No54900 (ground さん) に返信

> Expression.Invoke(add,
> Expression.Subtract(a, Expression.Constant(1)),
> Expression.Add(b, Expression.Constant(1)))),
この部分は
> Expression.LessThanOrEqual(a, Expression.Constant(0)),
によらず評価されるからではないでしょうか。
引用返信 編集キー/
■54909 / inTopicNo.3)  Re[2]: Expression.Lambda関数のtailCall引数
□投稿者/ ground (2回)-(2010/11/09(Tue) 13:08:45)
No54904 (shu さん) に返信
> 2010/11/09(Tue) 08:46:50 編集(投稿者)
>
> ■No54900 (ground さん) に返信
>
>>Expression.Invoke(add,
> > Expression.Subtract(a, Expression.Constant(1)),
> > Expression.Add(b, Expression.Constant(1)))),
> この部分は
> > Expression.LessThanOrEqual(a, Expression.Constant(0)),
> によらず評価されるからではないでしょうか。

すいません説明が足りませんでした。

引数を十分に小さくした場合、末尾再帰最適化の有無によらず使われるスタックが少ないため、
問題なく計算されます。
次の例では、正しく200が表示されます。

Console.WriteLine(addFunc(100, 100));

ですので、Expression.Condition() は問題ないと思われます。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -