Was sind "Lambda Ausdrücke"

Boron

Commander
Registriert
Sep. 2001
Beiträge
2.785
Hallo zusammen,

- bei einem Gespräch mit einem Kollegen, meinte dieser, dass "der kommende C++ Standard auch Lambda Funktionen unterstützt".
Meine Antwort war: "Oh toll, wird aber auch Zeit :confused_alt:!"
- In diesem Beitrag https://www.computerbase.de/forum/threads/c-gui.588628/#post-6087806 erwähnt Stefan_Sch auch Lambda Ausdrücke

Was zur Hölle sind das für Dinger und für was braucht man die?
Kann man mit diesen Konstrukten irgendwas besser erledigen, was anders auch möglich ist?

Ich habe mit diverse Seiten im Internet durchgelesen. Sogar bei den Großmeistern der MSDN persönlich.
Aber nicht eine einzige Seite konnte mir erklären wofür das gut ist. Oft unter der Bezeichnung "Anonyme Funktion" geführt frage ich mich was man mit einer Funktion machen kann die keinen Namen hat?
 
Wollt ich auch gerade reinkopieren...kurz gesagt:
Wenn du nicht schon weißt was das ist, brauchst du als normalsterblicher wohl Monate und Jahre um es zu kapieren....

Einführung in den λ-Kalkül Gute, etwas flippige Einführung in den λ-Kalkül (ca. 100 Seiten, als PS- und PDF-Dokument)
 
Zuletzt bearbeitet:
OK. Ich definiere eine "anonyme Funktion", die mir das Quadrat einer Zahl berechnet. Diese Funktion ist nur an einer Stelle nutzbar, nämlich an der Stelle, wo ich sie definiere.
Sollte ich eine Quadratfunktion noch einmal brauchen, definiere ich sie ein zweites mal, und ein drittes mal, und einer viertes mal usw.

Bis jetzt sehe ich keinerlei Vorteile, nur einen Nachteil.

Ich fand die Vorlesung "Theoretische Informatik" nicht besonders erbaulich. Ich bin mehr der Praktiker.
Was macht man also mit Lambdafunktionen in C++, C#, Scheme...? Welchen praktischen Nutzen haben sie in der Softwareentwicklung?
 
Zuletzt bearbeitet:
Oft nutzt man das z.B. für Callbackfunktionen: http://de.wikipedia.org/wiki/Rückruffunktion Letztlich kann man das verwenden ähnlich wie anonyme/innere Klassen, welche ja in Java auch sehr oft Anwendung finden (insbesondere wenn man mit Swing programmiert, vgl. z.B. http://www.dpunkt.de/java/Die_Sprache_Java/Objektorientierte_Programmierung_mit_Java/64.html ).
In manchen Sprachen kann man auch Funktionen dynamisch als String zusammenbauen (hat jetzt nicht zwingend mit anonymen Funktionen zu tun aber die nötigen Sprachkonstrukte braucht man im Allgemeinen).
 
Boron schrieb:
OK. Ich definiere eine "anonyme Funktion", die mir das Quadrat einer Zahl berechnet. Diese Funktion ist nur an einer Stelle nutzbar, nämlich an der Stelle, wo ich sie definiere.
Sollte ich eine Quadratfunktion noch einmal brauchen, definiere ich sie ein zweites mal, und ein drittes mal, und einer viertes mal usw.
Anonyme Funktionen setzt man eben auch nur da ein, wo man sie einmal braucht.

Beispiel Python:
Code:
liste = [1, 2, 3, 4]
print map(lambda x: x**2, liste) # [1, 4, 9, 16]
vs.
Code:
def quadriere(x):
    return x**2
liste = [1, 2, 3, 4]
print map(quadriere, liste) # [1, 4, 9, 16]

Spart Code und ist besser zu verstehen(weil man nicht erst nachgucken muss was quadriere macht). Klar kommt man auch ohne aus, aber while braucht man ja auch nicht, gibt ja jump. ;)

Anonyme Funktionen können auch genutzt werden um Kontrollstrukturen nachzubilden, als Beispiel sei Smalltalk genannt, das z.B. gar keine Kontrollstrukturen kennt
Code:
True ifTrue: [
    Transcript show: "Hallo Welt"
]
ifTrue: ist kein spezielles Sprachelement sondern einfach eine Methode die die von den eckigen Klammern begrenzte anonyme Funktion (hier Block genannt) ausführt.
 
Boron schrieb:
Was zur Hölle sind das für Dinger und für was braucht man die?

Um den Nutzen von Lambda Ausdrücken zu verstehen, muss man den Unterschied zwischen funktionaler und imperativer Programmierung verstehen. Lambda Ausdrücke ermöglichen nämlich eine funktionale Problemlösung. Normale Programmiersprachen, wie C, C++, C# und Java unterstützen in erster Linie die imperative Programmierung.

Das heißt, ich beschreibe detailliert was mein Code macht. Beim funktionalen Ansatz wird das Problem als Satz von auszuführenden Funktionen formuliert, ohne das die Reihenfolge der Berechnungen angegeben werden muss. Das Programm beschreibt lediglich Abhängigkeiten von Daten.

Wir sprechen hier also von Programmierparadigmen.

Nehmen wir das klassische Standardbeispiel. Wir suchen Mitarbeiter, deren Gehalt zwischen zwei Schranken liegt. Wir benötigen dies nur einmal im Programm. In C++ definieren wir dafür eine Funktion.

Code:
class between 
{
    double low, high;
public:
    between(double l, double u) : low(l), high(u) { }
    bool operator()(const employee& e) 
    {
        return e.salary() >= low && e.salary() < high;
    }
}

und rufen diese im Code wie folgt auf.

Code:
...
double min_salary;
...
std::find_if(employees.begin(), employees.end(), between(min_salary, 1.1 * min_salary));

Die Generierung von derartigen Funktionsobjekten ist aufwendig und fehleranfällig. Hier kommen Lambda Ausdrücke ins Spiel.

Den ganzen Kram kann ich nämlich anonymer in einer Zeile abarbeiten.

Code:
std::find_if(employees.begin(), employees.end(), <&>(const employee& e) (e.salary() >= min_salary && e.salary() < u_limit));

Der wesentliche Punkt ist, das bei der funktionalen Programmierung die Lesbarkeit und Verwaltbarkeit des Codes erhöht wird, weil das Lambda-Kalkül die vollständige Auswertung seperater Teilausdrücke gestattet. Man muss keine Variablen zuweisen. Dadurch gibt es weniger Programmierfehler, z.B. durch einen falsch zugewiesenen Wert. Ich muss mir auch keine Gedanken über den Kontrollfluss machen.

Bei der funktionalen Programmierung werden Zustands- und änderbare Daten vermieden, stattdessen steht die Anwendung von Funktionen im Vordergrund.

Die Fakultät kann ich daher einfach so schreiben.

Code:
Fakultat (x) { Fakultat = Fakultat(x-1) * x }

Das wars. Man sieht, es ist ein rein mathematischer Ansatz des Problems. Keine Variablenreservierung, keine explizite Programmflusskontrolle mit Schleifen, if, else, etc.. Mit dem Lambda Operator (=>) in C# 3.5 kann ich bequem Abbildungen beschreiben, statt explizit Rechenanweisungen zu schreiben.

Code:
List<int> ages = persons.ConvertAll(p => p.Age);

Das gibt mir die Liste mit den Altern von allen Personen, während

Code:
persons.RemoveAll(p => p.Age > 50);

mal schnell alle Personen aus meiner Liste entfernt, die älter als 50 sind. In Java müsste ich mittels foreach durch die Liste iterieren, mit if testen ob die Person älter als 50 ist und sie dann mit remove - ist immerhin Iterator safe - entfernen.

Code:
for(Person p : persons) {
    if(p.Age > 50) {
        persons.remove(p);
    }
}

Noch schmlimmer wird es, wenn ich mit Java beliebig nach Elementen sortieren wollte, Stichwort Comparable implementieren. Dann würde mein Code noch deutlich umfangreicher werden, während ich das in C# 3.5 auch mit einem Einzeiler abhaken kann.

Code:
persons.Sort((first, second) => first.Age.CompareTo(second.Age));

Rekursionen sind in imperativen Programmiersprachen zum Beispiel ein funktionaler Ansatz, der den meisten bekannt sein dürfte.
 
Zuletzt bearbeitet:
Na das ist für mich der Post des Monats Mai.
Selten habe ich eine so gute Antwort für eine Frage gelesen. Dafür also voll verdient
pokal.gif
.

Seit vier Jahren arbeite ich jetzt in der PKW-Steuergeräteprogrammierung mit C. C++ wird nur nebenher für kleine Tools, die uns das Leben/Entwickeln einfacher machen, benötigt.
Java oder C# is nich.
So abgefahrene Sachen da komplett an mir vorbei.
 
Boron schrieb:
Seit vier Jahren arbeite ich jetzt in der PKW-Steuergeräteprogrammierung mit C. C++ wird nur nebenher für kleine Tools, die uns das Leben/Entwickeln einfacher machen, benötigt.
Java oder C# is nich.
So abgefahrene Sachen da komplett an mir vorbei.

Steuergeräteprogrammierung, interessant! Ich bin ja ein heimlicher Fan der Sprache C. Sie ist inhaltlich präzise, kompakt, maschinennah und leistungsfähig. Einfach eine saubere Sprache ohne viel Schnörkel und großes Brimborium. Es lässt sich dennoch alles programmieren, weil sie Turing-vollständig ist und damit eine vollwertige Programmiersprache. Die Programme selbst können trotzdem sehr komplex sein.

Leider komme ich nur selten in den Genuß mit ihr programmieren zu können. In der Anwendungsentwicklung haben sich Java und C# zunehmend durchgesetzt, was selbstverständlich Gründe hat. Ich bin schon froh, wenn mal C++ zur Abwechslung verwendet wird.

Das soll nicht heißen, das Java oder C# schlecht sind. Es ist eben nur eine andere Art der Programmierung, auf einem abstrakterem Niveau.

Mit C# kann heute jeder Grundschüler eine Webclientanwendung programmieren. Klasse aufrufen, fertig. In C war das alles noch persönlicher, tiefgründiger und anspruchsvoller. Naja, ich schweife vom Thema ab...
 
Zurück
Oben