2009-07-03 15 views
27

Poniższa nie kompiluje:C#: Funkcje rekurencyjne z lambdas

Func<int, int> fac = n => (n <= 1) ? 1 : n * fac(n - 1); 

zmienna lokalna 'fac' nie może być zainicjowana przed uzyskaniem dostępu

Jak można zarabiać rekurencyjnej funkcji z lambdas?

[Aktualizacja]

Tutaj są również dwa linki, które znalazłem ciekawy otrzymuje brzmienie:

  1. Eric Lippert's "Why does a recursive lambda cause a definite assignment error?"
  2. Anonymous Recursion in C#
+2

Czy naprawdę chcesz? To wygląda na koszmar dla łatwości utrzymania i zrozumienia ... – Ian

+0

cóż, może tylko koncepcja –

Odpowiedz

45

Ten szczególny styl funkcja nie jest obsługiwana przez C# jako deklarację w jednym wierszu. Trzeba oddzielić deklaracji i definicji na 2 liniach

Func<int, int> fac = null; 
fac = n => (n <= 1) ? 1 : n * fac(n - 1); 
11

Musisz utworzyć fac pierwszy und przypisać ją później (co jest dość unfunctional ponieważ zależy od wielokrotnego przypisania) lub użyć tzw Y-combinators.

Przykład:

delegate Func<TIn, TOut> FixedPointFunction<TIn, TOut>(Func<TIn, TOut> f); 

static Func<T, TRes> Fix<T, TRes>(FixedPointFunction<T, TRes> f) { 
    return f(x => Fix(f)(x)); 
} 

static void Main(string[] args) { 

    var fact = Fix<int, int>(f => x => (x <= 1) ? x : x * f(x - 1)); 

    Console.WriteLine(fact(5));    
} 

Należy jednak pamiętać, że może to być nieco trudne do odczytania/zrozumieć.

15

Dobrze, jeśli właśnie wpisałeś "dlaczego rekurencyjna lambda powoduje błąd przydziału?" do jakiejś wyszukiwarki, znalazłbyś odpowiedź w moim artykule na ten temat.

:-)

http://blogs.msdn.com/ericlippert/archive/2006/08/18/why-does-a-recursive-lambda-cause-a-definite-assignment-error.aspx

+4

Wszystkie drogi prowadzą do Lipperta: D doskonały post. –

+3

+1 dla "jeśli właśnie wpisałeś" dlaczego rekurencyjna lambda powoduje określony błąd przypisania? " do jakiejś wyszukiwarki ":-) –

-1

od C# 7.0 w końcu może zrobić to w jednym wierszu używając local function

int fac(int n) => (n <= 1) ? 1 : n * fac(n - 1);