Funktionale Programmiersprachen
-
Hallo zusammen
Ich schreibe gerade eine kleine Arbeit über Lisp (habe in diesem Zusammenhang auch bereits zwei weitere Threads gestartet) und habe da noch einige ganz generelle Frage bezüglich von funktionalen Programmiersprachen:1. Wenn ja die funktionalen Programmiersprachen eigentlich viel besser sind als imperative (wird jedenfalls immer wieder gerne behauptet), wieso haben sich dann die imerativen viel erfolgreicher durchgesetzt?
2. Ist Lisp wirklich eine funktionale Programmiersprache? Ich habe während der Arbeit mit Lisp viel eher den Eindruck erhalten, dass es sich bei Lisp um eine gemischt paradigmatische Sprache mit einem starken Fokus auf das funktionale Programmierparadigma handelt.
Gründe:
- Lisp kennt die meisten Kontrollstrukturen aus imperativen Sprachen
- Lisp arbeitet Listen sequentiel (imperativ) ab.
- Lisp kennt globale Variablen, st also doch nicht Zustandslos (dadurch ist auch gleicht die Voraussetzung für Funktionen MIT Seiteneffekten gegeben...3. Wie realisiert man in einer (rein) funktionalen Programmiersprache folgende alltäglichen Aufgaben:
- einen Pseudo Random Number Generator? Funktionen in funktionalen Rrogrammiersprachen dürfen ja keine Seiteneffekte haben, weil man will, dass eine Funktion für den gleichen Input auch immer den gleichen Output hat. Doch genau bei rand() Funktion will man dies ja nicht, wie löst man dies?
- eine Statemachine (Wenn ich bei einer Maschine Knopf A das erste Mal drücke, soll etwas anderes passieren, als wenn ich ihn bereits zum zweiten Mal drücke (State Transition))?
Zustände sind ja generell verboten...- Ein Polling Mechanismus (bspw. für Pheripheriegeräte wie Tastatur, Maus und Joystick)?
Schleifen gibts ja nicht, nur Rekursion...Mfg Samuel
-
Ishildur schrieb:
- einen Pseudo Random Number Generator?
Rein funktional? Garnicht.
Ishildur schrieb:
- eine Statemachine
Siehe oben.
Ishildur schrieb:
- Ein Polling Mechanismus
Mit Endlosrekursion.
-
Ishildur schrieb:
1. Wenn ja die funktionalen Programmiersprachen eigentlich viel besser sind als imperative (wird jedenfalls immer wieder gerne behauptet)
Sind sie nicht. Das behaupten Leute, die zuerst eine imperative Sprache gelernt haben und später erst von funktionaler Programmierung erfahren. Tatsächlich sind rein funktionale Sprachen sehr eingeschränkt, deshalb winden sich reale Sprachen mit allerlei Tricks aus der Misere (Globale "stateful" Funktionen, Objektorientierte Erweiterungen, Systemlibrarys die Zustände haben, usw.)
-
Es kommt immer drauf an, was man machen will. Grundsätzlich sind funktionale Sprachen nicht besser als imperative. Aber bestimmte Aufgaben, lassen sich damit halt besser lösen.
Derzeit sind funktionale Sprachen wieder richtig beliebt. Das liegt imo einfach an der Tatsache, dass Multithreading durch die Mehrkernprozessoren immer wichtiger wird. Konnte man früher die Performance einfach über den Takt erhöhen, muss man Anwendungen heute parallelisieren. Und das geht halt bei funktionalen Programmen viel besser als bei imperativen. Anderes Beispiel ist natürlich (horizontale) Skalierung im Serverbereich. Dort ist funktionale Programmierung natürlich sehr spannend (siehe z.B. Google Map Reduce, Apache Hadoop).
IMHO wird in der Zukunft eine Mischung aus OOP + Funktionaler Programmierung das Rennen machen (siehe z.B. Scala). Aber meine Glaskugel ist dahingehend etwas trüb.
Edit: Andere sehr positive Eigenschaft von funktionalen Programme: Sie lassen sich viel einfacher automatisiert testen! Bester Beweis dafür ist der AXD301 switch:
In 1998, the AXD301 switch was announced, containing over a million lines of Erlang, and reported to achieve a reliability of nine "9"s.
-
HackerJoe schrieb:
Ishildur schrieb:
- einen Pseudo Random Number Generator?
Rein funktional? Garnicht.
Aber selbstverständlich geht das: Die Funktion randoms in Haskell nimmt einen Seed und liefert eine potentiell unendliche Liste (AKA Stream) von Pseudo-Zufallszahlen zurück. Das funktioniert in Haskell so ohne weiteres dank Lazy Evaluation. Dasselbe Prinzip würde auch in Lisp und anderen Sprachen funktionieren, wenn man vorher Streams, d.h. unendliche Listen, definiert.
Eine weniger elegante Alternative ist eine Funktion wie random, die einen Seed nimmt und das Paar (Pseudo-Zufallszahl, Neuer Seed) zurückgibt.
HackerJoe schrieb:
Ishildur schrieb:
- eine Statemachine
Siehe oben.
Eine Statemachine kann man mit Rekursion beschreiben. Oft sind Statemachines aber eng mit I/O verbunden. Wie man I/O rein funktional darstellen kann, ist keine einfache Frage. Haskell geht einen Weg über sogenannte "Monaden", wozu es unzählige Tutorials und Beschreibungen gibt.
Es gibt übrigens einen einen schönen Blog-Post, der erklärt, warum C rein funktional ist. Der Punkt ist, dass "Sprache X ist rein funktional" gar nicht so eindeutig definiert ist, wie man es gerne hätte. Am Ende muss jedes Programm, das vom Betriebssystem ausgeführt werden soll, Seiteneffekte besitzen.
-
@HackerJoe
Endlosrekursion
Also ich kann mir das irgendwie nicht so vorstellen. Erstens muss ja eine Funktion terminieren, um ein Resultat zurückgeben zu können und zweitens wäre hätte man doch innert Sekunden einen Stackoverflow.
Ich studiere Informatik mit dem Schwerpunkt Computer Perception and Virtual Reality und da arbeiten wir gerade mit verschiedenen Haptic System welche allesamt im kHz (über 1000 Pollings pro Sekunde) Bereich arbeiten. Also ich denke, dass da ein Stackoverflow nicht lange auf sich warten lassen würde?
-
-
Christoph schrieb:
HackerJoe schrieb:
Ishildur schrieb:
- einen Pseudo Random Number Generator?
Rein funktional? Garnicht.
Aber selbstverständlich geht das: Die Funktion randoms in Haskell nimmt einen Seed und liefert eine potentiell unendliche Liste (AKA Stream) von Pseudo-Zufallszahlen zurück. Das funktioniert in Haskell so ohne weiteres dank Lazy Evaluation.
In irgendeinem guten Buch wird das schön anschaulich erklärt, etwa so: anstatt Variablen zu betrachten, die sich mit der Zeit ändern, kann man die Zeit in diskrete Schritte teilen, und dann die geschwünschte Veränderung als Funktion der Zeit beschreiben. Scheinbar kann man die Zeit irgendwie loswerden, wenn man ihr einen Namen gibt.
-
1. Imperative Sprachen sind sicher verbreiteter, weil man sie früher schneller und effizienter implementieren konnte. Sie modellieren eben eher die Funktionsweise eines Computers. Bei funktionalen Programmiersprachen muss man ja einiges an Aufwand betreiben, um sie effizient auf das Modell eines üblichen Computers abzubilden (oder man baut einen speziellen Computer, wie man es eine Zeit für Lisp gemacht hat).
2. Lisp ist eine multiparadigmen Sprache. Man kann funktional, aber auch imperativ programmieren. Wenn du über funktionale Programmierung schreibst, solltest du dir auf jeden Fall auch Haskell anschauen.
-
Warum so kompliziert?
Will man die Seiteneffekte einer Funktion loswerden, müssen diese eben zur Ein- und Ausgabe der Funktion werden. In Haskell gibt es einen Zustand der Welt. Der wird dann der Main-Funktion übergeben. Alle Funktionen die was an der Aussenwelt verändern (Ein und Ausgabe z.B. oder auch das öffnen eines sockets), nehmen eben so einen Zustand der Welt als einen ihrer Parameter und geben einen neuen Zustand zurück. Natürlich ist dieser Zustand jetzt kein Datensatz sondern ne Abstraktion mit der man in Haskell nichts anderes tun kann, als ihn weiterzugeben, aber genau dafür ist er auch nur da.
Damit löst man nun einige Probleme. Seiteneffekte sind keine Seiteneffekte mehr und solche Funktionen haben nun eine konkrete Aufrufreihenfolge, denn sie benötigen ja die Ausgabe des Vorgängers als Eingabe.
Um nun aber nicht immer manuell diesen world Zustand weitergeben zu müssen, kommen Monaden ins Spiel. Das sind vereinfacht gesagt Glue-Funktionen, die diesen Welt-Zustand managen. Und mit ein bisschen syntaktischen Zucker, kann man dann Dinge in Haskell schreiben, die imperativ aussehen, aber tatsächlich rein funktional sind.
-
Also ich hab noch nie was mit funktionalen Programmiersprachen gemacht, aber für mich klingt das mit den Seifeneffekten und der Parallelität (was ja dort eben einfach sein soll) unrealistisch. Sobald ich irgendwas ausgeben will, habe ich doch Seiteneffekte. Wie kann ich z.B. eine Datei voller Zahlen einlesen, sortieren und auf dem Bildschirm ausgeben, ohne Seiteneffekte, so dass alles einfach parallelisiert werden kann? Muss ich mir dann schon mal mindestens den doppelten Speicher für die Liste besorgen, um sie einmal sortiert und einmal unsortiert zu halten? Wie kann man da überhaut ne Liste sortieren? Und wenn ich sie dann mal ausgeben, habe ich dann nicht Seiteneffekte auf dem Monitor?
-
Der Sinn ist nicht, absolut keine Seiteneffekte zu haben. Dann könnte man in der Tat keine sinnvollen Programme schreiben. Man will aber die Seiteneffekte unter Kontrolle kriegen und die "reinen" von den "unreinen" (pure/impure) Programmteilen abschotten.
-
WenigerSonnig schrieb:
Also ich hab noch nie was mit funktionalen Programmiersprachen gemacht, aber für mich klingt das mit den Seifeneffekten und der Parallelität (was ja dort eben einfach sein soll) unrealistisch. Sobald ich irgendwas ausgeben will, habe ich doch Seiteneffekte. Wie kann ich z.B. eine Datei voller Zahlen einlesen, sortieren und auf dem Bildschirm ausgeben, ohne Seiteneffekte, so dass alles einfach parallelisiert werden kann? Muss ich mir dann schon mal mindestens den doppelten Speicher für die Liste besorgen, um sie einmal sortiert und einmal unsortiert zu halten? Wie kann man da überhaut ne Liste sortieren? Und wenn ich sie dann mal ausgeben, habe ich dann nicht Seiteneffekte auf dem Monitor?
Natürlich kann man nicht alle Funktionsaufrufe mal eben so parallelisieren. Wenn Funktion A das Ergebnis von Funktion B braucht, dann hat man natürlich auch hier nur sequentielle Aufrufe. Aber da halt das Locken und Synchronisieren von gemeinsam genutzten Variablen wegfällt, geht es eben einfacher als bei imperativer Programmierung, wo an jeder Ecke irgendein Zustand gespeichert wird.
-
Ist Lisp wirklich eine funktionale Programmiersprache ... gemischt paradigmatische Sprache
Unter http://de.wikipedia.org/wiki/LISP schon mal in den Kasten rechts geschaut, unter Paradigmen ...