Anonymous Recursion in C# имеет потрясающее обсуждение на эту тему.
Рекурсия прекрасна и лямбда Конечная абстракция. Но как можно использовать ? Лямбда являются анонимными функциями и рекурсия требует имен ...
Поскольку это выскочило снова, вот пример использования 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 рекурсия. Например ...
// 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-комбинатор, он будет работать, как ожидалось ...
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 Link).
Точная жалоба VS2008 является: Local «сборки» Переменная не может быть инициализирована до получающий доступ. – Matt