2009-04-16 22 views
3

我在C#中使用遞歸lambda表達式,並發現了兩種方法在Web上執行此操作。一種方法使用fixed point combinator,另一種不使用。在下面的代碼中,f1是使用combinator構建的,而f2是直接定義的。我的問題是,我們是否需要C#中的定點組合器,或者該語言已經提供了我們需要的所有東西,所以我們可以讓它們獨立?我們需要C#中的定點組合器嗎?

class Program 
{ 
    static Func<T, T> F<T>(Func<Func<T,T>,Func<T,T>> f) 
    { 
     return x => f(F(f))(x); 
    } 

    static void Main(string[] args) 
    { 
     Func<Func<int,int>,Func<int,int>> f = fac => x => x == 0 ? 1 : x * fac(x - 1); 
     var f1 = F(f); 

     Console.WriteLine(f1(5)); 

     Func<int, int> f2 = null; 
     f2 = x => x == 0 ? 1 : x * f2(x - 1); 

     Console.WriteLine(f2(5)); 
    } 
} 

回答

4

由於我們可以給一個方法命名,這意味着該語言已經對內置的遞歸進行了必要的支持。

請注意,在您的問題中給出的第二種方法涉及到一個變量的值被引入後,改變它的值,使其不是「純」功能編程。 只有當你的函數演算系統沒有一個函數的內建函數時,Y定義完全定義之前,可以通過名稱引用它自己的定義。 C#有兩種方式直接做到這一點:1.最初將函數變量定義爲null,2.聲明普通的命名方法(迄今爲止的首選技術)。

+1

什麼有關的遞歸函數的memoization? – MichaelGG 2009-04-16 23:00:18

1

另一種方法是聲明你的遞歸函數功能的代表作爲靜態成員:

static Func<int, int> Factorial = (n) => n <= 1 ? 1 : n*Factorial(n - 1); 
-2

什麼是「需要」是什麼意思? C#不需要它們,因爲你不應該在C#中嘗試這種類型的函數式編程。這只是一個痛苦的途徑。

記憶一個遞歸函數是你想要一個定點組合器的地方。將C#Haskell進行比較。因此,在C#「需要」之前,需要做大量工作才能使這種編程合理實用。

3

我認爲它可以是相當優雅,稱爲遞歸一個額外的工具類,如下所示:

public static class Recursive { 
      public static Func<R> Func<R>(
       Func<Func<R>, Func<R>> f) { 
       return() => f(Func(f))(); } 
      public static Func<T1, R> Func<T1, R>(
       Func<Func<T1, R>, Func<T1, R>> f) { 
       return x => f(Func(f))(x); } 
      public static Func<T1, T2, R> Func<T1, T2, R>(
       Func<Func<T1, T2, R>, Func<T1, T2, R>> f) { 
       return (a1, a2) => f(Func(f))(a1, a2); 
      } 
      //And so on... 
     } 

class Program { 

    static void Main(string[] args) { 

     Console.WriteLine(
      Recursive.Func<int, int>(factorial => 
       x => x == 0 ? 1 : factorial(x - 1) * x 
      ) 
      (10) 
     ); 

     Console.WriteLine(
      Recursive.Func<int,int,int>(gcd => 
       (x,y) => 
        x == 0 ? y: 
        y == 0 ? x: 
        x > y ? gcd(x % y, y): 
        gcd(y % x, x) 
      ) 
      (35,21) 
     ); 
    } 
}