2010-09-02 14 views
7

i Accelerated C# lese ich den folgenden Code nicht wirklich verstehen:Benötigen Sie Hilfe bei Lambda (currying) Verständnis

public static Func<TArg1, TResult> Bind2nd<TArg1, TArg2, TResult> (
    this Func<TArg1, TArg2, TResult> func, 
    TArg2 constant) 
{ 
    return (x) => func(x, constant); 
} 

in der letzten Zeile, was zu x bezieht? und es gibt noch einen anderen:

public static Func<TArg2, Func<TArg1, TResult>> Bind2nd<TArg1, TArg2, TResult> 
(this Func<TArg1, TArg2, TResult> func) 
{ 
    return (y) => (x) => func(x, y); 
} 

Wie bewerte ich das? (y) => (x) => func(x, y) was passiert wo ... verwirrend.

Antwort

19

Let zuerst den Code vereinfachen:

Func<int, int> B(Func<int, int, int> f, int c) 
{ 
    return x=>f(x, c); 
} 

Dies ist genau das gleiche wie:

class Locals 
{ 
    public int c; 
    public Func<int, int, int> f; 
    public int Magic(int x) { return f(x, c); } 
} 
Func<int, int> B(Func<int, int, int> f, int c) 
{ 
    Locals locals = new Locals(); 
    locals.f = f; 
    locals.c = c; 
    return locals.Magic; 
} 

Nun ist es klar, worauf bezieht sich x? x ist der Parameter für die Funktion "Magic".

Jetzt können Sie B wie folgt verwenden:

Func<int, int, int> adder = (a, b)=>a+b; 
Func<int, int> addTen = B(adder, 10); 
int thirty = addTen(20); 

Sinn? Siehst du, was hier passiert? Wir nehmen eine Funktion von zwei Parametern und "fixieren" einen der Parameter zu einer Konstante. Es wird also eine Funktion eines Parameters.

Das zweite Beispiel geht einen Schritt weiter. Wieder vereinfachen des cruft loszuwerden, damit Sie es leichter verstehen:

Func<int, Func<int, int>> B2(Func<int, int, int> f) 
{ 
    return y=>x=>f(x,y); 
} 

Dies ist die gleiche wie

ist
class Locals3 
{ 
    public int y; 
    public int Magic3(int x) 
    { 
     return x + this.y; 
    } 
} 
class Locals2 
{ 
    public Func<int, int, int> f; 
    public Func<int, int> Magic2(int y) 
    { 
     Locals3 locals = new Locals3; 
     locals.y = y; 
     return locals.Magic3; 
    } 
} 

Func<int, Func<int, int>> B2(Func<int, int, int> f) 
{ 
    Locals2 locals = new Locals2(); 
    locals.f = f; 
    return locals.Magic2; 
} 

So sagen Sie

Func<int, int, int> adder = (a, b)=>a+b; 
Func<int, Func<int, int>> makeFixedAdder = B2(adder); 
Func<int, int> add10 = makeFixedAdder(10); 
int thirty = add10(20); 

B a Parameterfixierer. B2 macht einen Parameter-Fixierer für Sie.

Das ist jedoch nicht der Punkt von B2. Der Punkt ist, dass B2:

adder(20, 10); 

das gleiche Ergebnis wie

B2(adder)(20)(10) 

B2 gibt schaltet eine Funktion von zwei Parametern in zwei Funktionen eines Parameters jedes.

Sinn machen?

+0

Ich muss mich bedanken für Ihre ausführliche Erklärung. Jetzt verstehe ich es auch :) – Riaan

1

x ist der Parameter des Lambdas, es ist vom Typ TArg1.

Es kann hilfreich sein, das => als "maps to" auszusprechen, wie in "x mappt eine neue Funktion mit einer Konstante des Typs TArg2, die in den ursprünglichen Funktionsdelegaten func eingefügt wird."

+0

Nur ein Add, sagt MSDN liest '=>' wie * geht zu *. –

1

Die Variable x ist eine nicht gebundene Variable. Dies stellt ein Argument für die zurückgegebene Funktion vom Aufruf Bind2nd.

Ein paar Stunden mit Scheme würde Ihnen hier helfen, aber versuchen Sie es.

Wenn Sie Bind2nd aufrufen, ist das zurückgegebene Ergebnis eine Funktion. Diese Funktion ist definiert als

(x) => func (x, constant) 

Nun, da Sie die oben einer Variablen zugewiesen haben, lässt lambda sagen, können Sie diese Funktion über die Variable lambda

lambda(x); 
ist

Die x definiert in Bind2nd nennen kann nur Eine Variable, die ein Argument für die Funktion darstellt, die an Sie zurückgegeben wird.

1

Ein Lambda-Ausdruck ist eine Abkürzung für anonyme Methode. Wie die anonyme Methode wird der Lambda-Ausdruck den Delegattypen zugewiesen. Alle Bedingungen, die für anonyme Methoden gelten, gelten auch für Lambda-Ausdrücke.

=> heißt Lambda-Operator, der als "goes to" gelesen wird. Die linke Seite des Operators gibt die durch Komma getrennten Eingabeparameter an, und die rechte Seite gibt einen Ausdrucks- oder Anweisungsblock an, der als Lambda-Text bezeichnet wird. (p1, p2, p3, ... pN) => Ausdruck Wenn Sie nur einen Parameter haben, können Sie die Klammer überspringen p1 => Ausdruck;

Ich habe ein kleines Blog erklären Lambda-Ausdruck hier schriftliche Lambda Expression

Verwandte Themen