2009-02-23 12 views
12

Warum die Sprache C# Designer möglicherweise nicht Unterstützung, wie dies für etwas aufgenommen haben (portiert von Structure and Interpretation of Computer Programs, zweite Auflage, S. 30..):Warum hat C# keine lexikalisch verschachtelten Funktionen?

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

Antwort

36

In der Tat hat C# genau dies.

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. Außer für den richtig tail-rekursiven Teil. :) –

+1

Ja, C# wird die Tail-Rekursion nicht zu einer Schleife optimieren. * Diese * Funktion fehlt in der Sprache. – yfeldblum

+0

Vielen Dank für das Hinweis! Ich muss auf einen Wechsel zu .NET 3.5 drängen (wir benutzen unerklärlicherweise immer noch 2.0). –

8

Wie Gerechtigkeit sagte, können Sie es mit C# 3.5 und lambdas tun; wenn Sie C# 2.0 haben, können Sie anonyme Funktionen verwenden, obwohl es etwas weniger sexy sein würde:

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

Edit: Ich habe vergessen, ist Func nicht in C# definiert 2.0, so dass Sie es selbst definieren:

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