2009-02-23 60 views
12

爲什麼會在C#語言的設計者沒有包括這樣的事情(從Structure and Interpretation of Computer Programs移植,第二版,第30頁。)支持:爲什麼C#沒有詞彙嵌套函數?

/// <summary>Return the square root of x.</summary> 
double sqrt(double x) { 
    bool goodEnough(double guess) { 
    return Math.Abs(square(guess) - x) < 0.001; 
    } 
    double improve(double guess) { 
    return average(guess, x/guess); 
    } 
    double sqrtIter(double guess) { 
    return goodEnough(guess) ? guess : sqrtIter(improve(guess)); 
    } 
    sqrtIter(1.0); 
} 

回答

36

事實上,C#有正是這種。

double sqrt(double x) { 
    var goodEnough = new Func<double, bool>(guess => 
     Math.Abs(square(guess) - x) < 0.001 
    ); 
    var improve = new Func<double, double>(guess => 
     average(guess, x/guess) 
    ); 
    var sqrtIter = default(Func<double, double>); 
    sqrtIter = new Func<double, double>(guess => 
     goodEnough(guess) ? guess : sqrtIter(improve(guess)) 
    ); 
    return sqrtIter(1.0); 
} 
+2

+1。除了正確的尾遞歸部分。 :) – 2009-02-23 02:50:39

8

Like Justice說,你可以用C#3.5和lambdas來做到這一點;如果你有C#2.0中,你可以使用匿名函數,儘管這有些不太性感:

double sqrt(double x) { 
    Func<double, bool> goodEnough = delegate(double guess) { 
     return Math.Abs(square(guess) - x) < 0.001; 
    }; 
    Func<double, double> improve = delegate(double guess) { 
     return average(guess, x/guess); 
    }; 
    Func<double, double> sqrtIter = null; 
    sqrtIter = delegate(double guess) { 
     return goodEnough(guess) ? guess : sqrtIter(improve(guess)); 
    }; 
    return sqrtIter(1.0); 
} 

編輯:我忘了,Func鍵沒有在C#2.0中定義的,所以你要自己定義:

public delegate TResult Func<T, TResult>(T guess);