Anonymous Recursion in C# 对此话题进行了精彩的讨论。
递归很漂亮,而 lambdas 很漂亮
终极抽象。但是怎么可能
它们可以一起使用吗? Lambda 是
匿名函数和递归
需要名字...
既然这又弹出来了,下面是一个使用 Y-combinator 的例子:
// 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-combinator 并仅使用委托设置递归,则不会获得正确的递归。比如……
// This is BAD. Do not do this!
Func<int,int> badRec = null;
badRec = x => ( x <= 1 ) ? 1 : x * badRec( x - 1 );
但一切正常......
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-combinator,它将按预期工作......
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 链接)的更多信息。