Anonymous Recursion in C#在這個話題上有很好的討論。
遞歸很漂亮,lambda是 的最終抽象。但 他們怎麼可以一起使用? Lambda表達式是 匿名函數和遞歸 需要的名字......
由於這再次彈起,這裏使用的Y組合子的例子:
// This is the combinator
public static Func<A,R> Y<A,R>(Func<Func<A,R>, Func<A,R>> f)
{
Func<A,R> g = null;
g = f(a => g(a));
return g;
}
這裏的它的使用來調用匿名遞歸函數...
Func<int,int> exp = Y<int,int>(e => x => (x <=1) ? 1 : x * e(x - 1));
Console.WriteLine(exp(5));
你會注意到,如果你不使用的Y組合子,併成立了遞歸只委託,你沒有得到CORRE ct遞歸。例如...
但一切工作正常...
Console.WriteLine(badRec(5));
// Output
// 120
但試試這個...
Func<int,int> badRec = null;
badRec = x => (x <= 1) ? 1 : x * badRec(x - 1);
Func<int,int> badRecCopy = badRec;
badRec = x => x + 1;
Console.WriteLine(badRec(4));
Console.WriteLine(badRecCopy(5));
// Output
// 5
// 25
什麼?!?
你看,行badRec = x => x + 1;
後,你確實有委託是這樣的......
badRecCopy = x => (x <= 1) ? 1 : x * ((x+1)-1);
所以,badRec由1我們預計(4+1=5)
增加值,但是現在badRecCopy實際上返回價值(5*((5+1)-1)
的平方,我們幾乎可以肯定沒有想到。
如果您使用的Y組合子,它會如預期...
Func<int,int> goodRec = Y<int,int>(exp => x => (x <=1) ? 1 : x * exp(x - 1));
Func<int,int> goodRecCopy = goodRec;
,你會得到你所期望的。
goodRec = x => x + 1;
Console.WriteLine(goodRec(4));
Console.WriteLine(goodRecCopy(5));
// Output
// 5
// 120
您可以閱讀更多關於Y-combinator(PDF鏈接)。
從VS2008確切的抱怨是:局部變量「構建」可能不被初始化之前訪問。 – Matt 2009-07-30 19:15:33