2009-07-03 7 views
27

Le ci-après ne compilent pas:C#: Fonctions récursives avec lambdas

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

Variable locale 'fac' pourrait ne pas être initialisés avant d'accéder à

Comment pouvez-vous faire une fonction récursive avec lambdas?

[Mise à jour]

Voici également deux liens que je trouve intéressant à lire:

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

Voulez-vous vraiment? Cela ressemble à un cauchemar pour la maintenabilité et la compréhension ... – Ian

+0

bien, peut-être juste un concept –

Répondre

45

Ce style particulier de la fonction est pas prise en charge par C# comme une déclaration de ligne unique. Vous devez séparer la déclaration et la définition en 2 lignes

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

Vous devez créer fac d'abord und assigner plus tard (ce qui est assez unfunctional car cela dépend de l'affectation multiple) ou d'utiliser ce qu'on appelle Y-combinators.

Exemple:

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));    
} 

Mais notez que cela pourrait être un peu difficile à lire/comprendre.

15

Eh bien, si vous venez de taper "pourquoi un lambda récursif provoque une erreur d'affectation définie?" dans un moteur de recherche, vous auriez trouvé la réponse dans mon article sur le sujet.

:-)

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

+4

Tous les chemins mènent à Lippert: D excellent poste. –

+3

+1 pour 'si vous venez de taper' pourquoi un lambda récursif provoque-t-il une erreur d'affectation définie? ' dans un moteur de recherche ':-) –

-1

depuis C# 7.0 enfin pouvez faire en une seule ligne en utilisant un local function

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