it-swarm-eu.dev

Was ist ein Lambda und warum sollte es nützlich sein?

Bisher habe ich gehört von:

  • Lambda-Kalkül
  • Lambda-Programmierung
  • Lambda-Ausdrücke
  • Lambda-Funktionen

Was alles mit funktionaler Programmierung zu tun zu haben scheint ...

Anscheinend wird es in C++ 1x integriert, also könnte ich es jetzt besser verstehen:

http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions

Kann jemand kurz definieren, was Lambdas Dinge sind und wo es nützlich sein kann?

55
jokoon
  • Lambda-Kalkül

Der Lambda-Kalkül ist ein Rechenmodell, das in den 30er Jahren von der Alonzo-Kirche erfunden wurde. Die Syntax und Semantik der meisten funktionalen Programmiersprachen ist direkt oder indirekt vom Lambda-Kalkül inspiriert.

Der Lambda-Kalkül in seiner grundlegendsten Form hat zwei Operationen: Abstraktion (Erstellen einer (anonymen) Funktion) und Anwendung (Anwenden einer Funktion). Die Abstraktion wird unter Verwendung des λ-Operators durchgeführt, wobei dem Lambda-Kalkül sein Name gegeben wird.

  • Lambda-Ausdrücke
  • Lambda-Funktionen

Anonyme Funktionen werden oft als "Lambdas", "Lambda-Funktionen" oder "Lambda-Ausdrücke" bezeichnet, da λ, wie oben erwähnt, das Symbol zum Erstellen anonymer Funktionen im Lambda-Kalkül war (und das Wort lambda verwendet wird) aus demselben Grund anonyme Funktionen in vielen LISP-basierten Sprachen erstellen).

  • Lambda-Programmierung

Dies ist kein häufig verwendeter Begriff, aber ich gehe davon aus, dass er das Programmieren mit anonymen Funktionen oder das Programmieren mit Funktionen höherer Ordnung bedeutet.


Ein bisschen mehr Informationen über Lambdas in C++ 0x, ihre Motivation und ihre Beziehung zu Funktionszeigern (vieles davon ist wahrscheinlich eine Wiederholung dessen, was Sie bereits wissen, aber ich hoffe, es hilft, die Motivation von Lambdas zu erklären und wie sie sich unterscheiden von Funktionszeigern):

Funktionszeiger, die bereits in C vorhanden waren, sind z.B. Übergeben Sie eine Vergleichsfunktion an eine Sortierfunktion. Ihre Nützlichkeit ist jedoch begrenzt:

Wenn Sie beispielsweise einen Vektorvektor nach dem i -ten Element jedes Vektors sortieren möchten (wobei i ein Laufzeitparameter ist), können Sie dies nicht mit einem Funktionszeiger lösen. Eine Funktion, die zwei Vektoren anhand ihres i -ten Elements vergleicht, müsste drei Argumente (i und die beiden Vektoren) annehmen, aber die Sortierfunktion würde eine Funktion benötigen, die zwei Argumente akzeptiert. Was wir brauchen würden, ist eine Möglichkeit, das Argument i irgendwie an die Funktion zu liefern, bevor es an die Sortierfunktion übergeben wird, aber wir können dies nicht mit einfachen C-Funktionen tun.

Um dies zu lösen, führte C++ das Konzept der "Funktionsobjekte" oder "Funktoren" ein. Ein Funktor ist im Grunde ein Objekt, das eine operator() -Methode hat. Jetzt können wir eine Klasse CompareByIthElement definieren, die das Argument i als Konstruktorargument verwendet und dann die beiden zu vergleichenden Vektoren als Argumente mit der Methode operator() verwendet. Um einen Vektor von Vektoren nach dem i -ten Element zu sortieren, können wir jetzt ein CompareByIthElement -Objekt mit i als Argument erstellen und dieses Objekt dann an die Sortierfunktion übergeben.

Da Funktionsobjekte nur Objekte und keine technischen Funktionen sind (obwohl sie sich so verhalten sollen), können Sie keinen Funktionszeiger auf ein Funktionsobjekt verweisen lassen (Sie können natürlich einen Zeiger auf ein Funktionsobjekt haben, aber es hätte einen Typ wie CompareByIthElement* und wäre somit kein Funktionszeiger).

Die meisten Funktionen in der C++ - Standardbibliothek, die Funktionen als Argumente verwenden, werden mithilfe von Vorlagen definiert, sodass sie sowohl mit Funktionszeigern als auch mit Funktionsobjekten funktionieren.

Nun zu Lambdas:

Das Definieren einer ganzen Klasse zum Vergleichen durch das i -te Element ist etwas ausführlich, wenn Sie sie nur einmal zum Sortieren eines Vektors verwenden möchten. Selbst wenn Sie nur einen Funktionszeiger benötigen, ist das Definieren einer benannten Funktion nicht optimal, wenn sie nur einmal verwendet wird, da a) der Namespace verschmutzt wird und b) die Funktion normalerweise sehr klein ist und nicht wirklich vorhanden ist Ein guter Grund, die Logik in eine eigene Funktion zu abstrahieren (ansonsten können Sie keine Funktionszeiger haben, ohne eine Funktion zu definieren).

Um dies zu beheben, wurden Lambdas eingeführt. Lambdas sind Funktionsobjekte, keine Funktionszeiger. Wenn Sie ein Lambda-Literal wie [x1, x2](y1,y2){bla} verwenden, wird Code generiert, der im Wesentlichen Folgendes bewirkt:

  1. Definieren Sie eine Klasse mit zwei Mitgliedsvariablen (x1 Und x2) Und einem operator() mit den Argumenten (y1 Und y2). und der Körper bla.
  2. Erstellen Sie eine Instanz der Klasse und setzen Sie die Mitgliedsvariablen x1 Und x2 Auf die Werte der Variablen x1 Und x2, Die sich derzeit im Gültigkeitsbereich befinden.

Lambdas verhalten sich also wie Funktionsobjekte, außer dass Sie nicht auf die Klasse zugreifen können, die generiert wurde, um ein Lambda auf andere Weise als mit dem Lambda zu implementieren. Folglich akzeptiert jede Funktion, die Funktoren als Argumente akzeptiert (was im Grunde genommen jede Nicht-C-Funktion in der Standardbibliothek bedeutet), Lambdas, aber jede Funktion, die nur Funktionszeiger akzeptiert, nicht.

43
sepp2k

Grundsätzlich sind Lambda-Funktionen Funktionen, die Sie "on the fly" erstellen. In C++ 1x könnten sie verwendet werden, um die Unterstützung für die funktionale Programmierung zu verbessern:

std::for_each( begin, end, [](int i){std::cout << i << '\n';} );

Dies führt ungefähr zu einem Code ähnlich dem folgenden:

struct some_functor {
  void operator()(int i) {std::cout << i << '\n';}
};

std::for_each( begin, end, some_functor() );

Wenn Sie some_functor Nur für diesen einen Aufruf von std::for_each() benötigen, hat diese Lambda-Funktion mehrere Vorteile gegenüber:

  • was in der Schleife gemacht wird, wird genau dort angegeben, wo die Schleifenfunktion aufgerufen wird
  • es entlastet Sie davon, einen Teil des Kesselplattencodes zu schreiben
  • es gibt keinen Funktor, der in einem Namespace-Bereich herumliegt und alle, die sich den Code ansehen, fragen, wofür er benötigt wird
18
sbi

Eine Lambda-Funktion ist ein anderer Name für eine anonyme Funktion - im Wesentlichen eine Funktion ohne Namen.

Normalerweise verwenden Sie dies in Sprachen, in denen Sie die Funktion nur einmal verwenden müssen. Zum Beispiel statt

def add(a, b)
  return a+b

und dann diese Funktion an eine andere Funktion wie diese übergeben

reduce(add, [5,3,2])

Mit einem Lambda würden Sie einfach tun

reduce(lambda x, y: a+b, [5,3,2])
7
Martin Konecny