Mit Generatoren und Lambda können wir mit Python funktionale Programmierung durchführen. Mit Ruby können Sie dasselbe auch erreichen.
Die Frage ist also: Warum brauchen wir bestimmte funktionale Programmiersprachen wie Erlang, Haskell und Scheme? Gibt es etwas anderes, das diese spezifischen funktionalen Programmiersprachen bieten? Warum können wir Python nicht einfach für die funktionale Programmierung verwenden?
programming-languages
python
functional-programming
Joshua Partogi
quelle
quelle
Antworten:
Ich schätze die Frage, weil ich persönlich ein großer Fan von Python und funktionalem Programmierstil bin. Ich habe einen langen Hintergrund in Python und habe vor kurzem angefangen, Haskell zu lernen. Hier sind einige Punkte, die auf meinen persönlichen Erfahrungen mit den Unterschieden zwischen diesen Sprachen aus funktionaler Sicht basieren.
Reinheit
Auch wenn Sie sich nicht für die Reinheit der Funktionen interessieren (dh keine Nebenwirkungen haben), hat dies praktische Auswirkungen darauf, wie einfach es ist, Code und die Gründe dafür zu lesen. Selbst wenn Sie die Reinheit Ihrer eigenen Python-Funktionen beibehalten, besteht ein großer Unterschied darin, dass der Compiler die Reinheit erzwingt und vor allem die Standardbibliothek auf Reinheit und unveränderlichen Datenstrukturen basiert.
Performance
Die Leistung ist Ihnen je nach Anwendungsdomäne vielleicht egal oder auch nicht, aber statische Typisierung und garantierte Reinheit bieten dem Compiler im Vergleich zu Python und anderen dynamischen Sprachen viel mehr Möglichkeiten zum Arbeiten (obwohl ich zugeben muss, dass PyPy großartig ist Einbrüche, und zB grenzt LuaJIT an ein Wunder).
Tail-Call-Optimierung
Bezogen auf die Leistung, aber etwas anders. Auch wenn Sie sich nicht zu sehr für die Laufzeitleistung interessieren, schränkt die fehlende Tail-Call-Optimierung (insbesondere für die Tail-Rekursion) die Möglichkeiten ein, Algorithmen in Python zu implementieren, ohne die Stack-Grenzen zu überschreiten.
Syntax
Dies ist der Hauptgrund, warum ich angefangen habe, mir "echte" funktionale Sprachen anzuschauen, anstatt nur Python mit funktionalem Stil zu verwenden. Obwohl ich denke, dass Python im Allgemeinen eine sehr ausdrucksstarke Syntax hat, weist es einige Schwachstellen auf, die für die funktionale Codierung spezifisch sind. Beispielsweise:
f = g . h
vs.f = lambda *arg: g(h(*arg))
f = map g
vs.f = functools.partial(map, g)
sum = reduce (+) lst
vs.sum = reduce(operator.add, lst)
y = func1 $ func2 $ func3 x
leichter zu lesen, alsy = func1(func2(func3(x)))
wenn Sie mit dieser Notation vertraut sind.quelle
Das sind die wichtigsten Unterschiede:
Haskell
Haskell und Erlang
Erlang
Planen
Alle Sprachen
Außerdem sollten Sie sich Sprachen aus der ML-Familie wie SML, Ocaml und F # und Scala ansehen, die OO und funktionale Programmierung auf eine neue Art und Weise verschmelzen. Alle diese Sprachen haben einzigartige interessante Eigenschaften.
quelle
Es ist schwierig, genau zu definieren, was eine "funktionale Sprache" ist - von den von Ihnen aufgelisteten Sprachen ist nur Haskell rein funktional (alle anderen verwenden einen hybriden Ansatz). Es gibt jedoch einige Sprachfunktionen, die für die funktionale Programmierung sehr hilfreich sind, und Ruby und Python haben nicht genug davon, um für FP sehr gute Umgebungen zu sein. Hier ist meine persönliche Checkliste in der Reihenfolge ihrer Wichtigkeit:
Der Bedarf an (1) sollte offensichtlich sein - Funktionen höherer Ordnung sind ohne erstklassige Funktionen äußerst schwierig. Wenn Leute darüber reden, dass Ruby und Python gute Sprachen für FP sind, reden sie normalerweise darüber. Diese spezielle Funktion ist jedoch notwendig, aber nicht ausreichend, um eine Sprache für FP zu verbessern.
(2) ist seit der Erfindung von Scheme eine traditionelle Notwendigkeit für FP. Ohne TCO ist es unmöglich, mit tiefer Rekursion zu programmieren, was einer der Eckpfeiler von FP ist, da Stapelüberläufe auftreten. Die einzige "funktionale" Sprache (laut populärer Definition), die dies nicht bietet, ist Clojure (aufgrund der Einschränkungen der JVM), aber Clojure verfügt über eine Vielzahl von Hacks, um die Gesamtbetriebskosten zu simulieren. (Zu Ihrer Information, Ruby TCO ist implementierungsspezifisch , aber Python unterstützt es nicht speziell .) Der Grund, warum TCO garantiert werden muss, ist, dass tief rekursive Funktionen bei einigen Implementierungen nicht funktionieren, so dass Sie es nicht wirklich können benutze sie überhaupt.
(3) ist eine weitere große Sache, die moderne funktionale Sprachen (insbesondere Haskell, Erlang, Clojure und Scala) nicht haben, wie Ruby und Python. Ohne zu sehr ins Detail zu gehen, beseitigt die garantierte Unveränderlichkeit ganze Klassen von Fehlern, insbesondere in gleichzeitigen Situationen, und ermöglicht saubere Dinge wie dauerhafte Datenstrukturen . Es ist sehr schwierig, diese Vorteile ohne Sprachunterstützung zu nutzen.
(4) ist für mich das Interessanteste an rein funktionalen Sprachen (im Gegensatz zu Hybridsprachen). Betrachten Sie die folgende extrem einfache Ruby-Funktion:
Dies sieht nach einer reinen Funktion aus, kann jedoch aufgrund der Überladung des Operators zu einer Veränderung der Parameter oder zu Nebenwirkungen wie dem Drucken auf der Konsole führen. Es ist unwahrscheinlich, dass jemand den
+
Bediener überlastet , um eine Nebenwirkung zu haben, aber die Sprache gibt keine Garantie. (Das Gleiche gilt für Python, auch wenn dies in diesem Beispiel möglicherweise nicht der Fall ist.)In einer rein funktionalen Sprache hingegen gibt es Garantien auf Sprachebene, dass Funktionen referenziell transparent sind. Dies hat zahlreiche Vorteile: reine Funktionen können leicht gespeichert werden; Sie können einfach getestet werden, ohne auf irgendeinen globalen Zustand angewiesen zu sein. und Werte innerhalb der Funktion können träge oder parallel ausgewertet werden, ohne sich um Parallelitätsprobleme kümmern zu müssen. Haskell nutzt dies voll aus, aber ich weiß nicht genug über andere funktionale Sprachen, um zu wissen, ob sie es tun.
Trotzdem ist es möglich, FP-Techniken in fast jeder Sprache (sogar Java) einzusetzen. Zum Beispiel ist Googles MapReduce von funktionalen Ideen inspiriert, aber soweit ich weiß, verwenden sie keine "funktionalen" Sprachen für ihre großen Projekte (ich denke, sie verwenden hauptsächlich C ++, Java und Python).
quelle
Die Sprachen, die Sie erwähnen, sind sehr unterschiedlich.
Während Python und Ruby dynamisch typisierte Sprachen sind, ist Haskell statisch typisiert. Erlang ist eine konkurrierende Sprache, die das Actor-Modell verwendet und sich von allen anderen von Ihnen erwähnten Sprachen stark unterscheidet.
Python und Ruby haben viele imperative Konstrukte, während in einer reineren funktionalen Sprache wie Haskell alles etwas zurückgibt oder mit anderen Worten, alles eine Funktion ist.
quelle
Wie immer zu spät zur Party, aber ich werde sowieso Dinge sagen.
Eine funktionale Programmiersprache ist keine Sprache, die eine funktionale Programmierung ermöglicht. Wenn wir uns an diese Definition halten, dann ist so ziemlich jede Sprache irgendwo eine funktionale Programmiersprache. (Dies gilt übrigens auch für OOP. Sie können in C in einem OOP-Stil schreiben, wenn Sie möchten. Entsprechend Ihrer Logik ist C also eine OOP-Sprache.)
Was macht eine funktionale Programmiersprache ist nicht das, was es erlaubt , Ihnen zu Programm wie, es ist , was es lässt Sie wie programmieren leicht . Das ist der Schlüssel.
Also, Python hat Lambdas (die unglaublich anämische schließungsähnliche Vorgänge sind) und bietet Ihnen ein paar Bibliotheksfunktionen, die Sie in funktionalen Bibliotheken sehen werden, wie "map" und "fold". Dies ist jedoch nicht genug, um es zu einer funktionalen Programmiersprache zu machen, da es schwierig bis unmöglich ist, darin konsequent einen geeigneten funktionalen Stil zu programmieren (und die Sprache erzwingt diesen Stil mit Sicherheit nicht!). Im Kern ist Python eine imperative Sprache, die sich mit Zuständen und Zustandsmanipulationsoperationen befasst, und dies steht einfach im Widerspruch zu dem Ausdruck und der Ausdrucksbewertungssemantik einer funktionalen Sprache.
Warum haben wir also funktionale Programmiersprachen, wenn Python (oder Ruby (oder fügen Sie die Sprache Ihrer Wahl ein)) "funktionale Programmierung" durchführen kann? Da Python et al. Keine ordnungsgemäße funktionale Programmierung durchführen können. Deshalb.
quelle
Sie können funktionale Programmierung in Java durchführen (siehe zB http://functionaljava.org/ ). Sie können in C auch objektorientiert programmieren . Es ist einfach nicht so idiomatisch.
Wir brauchen also nicht unbedingt Erlang, Haskell, Scheme oder eine bestimmte Programmiersprache, aber alle stehen für unterschiedliche Ansätze und Kompromisse, was einige Aufgaben einfacher und andere schwieriger macht. Was Sie verwenden sollten, hängt davon ab, was Sie erreichen möchten.
quelle
Diese Frage kann auf eine unendliche Anzahl von Sprachen und Paradigmen angewendet werden.
Die meisten, wenn nicht alle Sprachen existieren aus einem bestimmten Grund. Sie existieren, weil jemand ein Bedürfnis hatte, das nicht oder nur unzureichend mit der aktuellen Sprache gefüllt war. (Dies gilt natürlich nicht für jede Sprache, aber ich denke, es gilt für die meisten bekannten Sprachen.) Beispielsweise wurde Python ursprünglich für die Schnittstelle mit dem Amoeba-Betriebssystem [ 1 , 2 ] entwickelt und Erlang wurde als Hilfe entwickelt bei der Entwicklung von Telefonieanwendungen [ 3 ]. Also eine Antwort auf die Frage "Warum brauchen wir eine andere funktionale Sprache?" kann einfach sein, weil [Name-von-jemand-einfügen-,-der-weiß-wie-zu-Design-Sprachen] die Art und Weise, wie Python es tat, nicht mochte.
Das fasst ziemlich genau zusammen, was ich denke, die Antwort ist. Während Sie mit Python alles tun können, was Sie mit einer funktionalen Sprache tun können, möchten Sie das wirklich? Alles, was Sie in C tun können, können Sie in der Montage tun, aber möchten Sie? Verschiedene Sprachen sind immer am besten in der Lage, verschiedene Dinge zu tun, und so sollte es auch sein.
quelle
Bei der funktionalen Programmierung geht es sowohl um ein Designparadigma als auch um spezifische Sprachmerkmale. Oder anders ausgedrückt, Lambdas und eine Kartenfunktion machen keine funktionierende Programmiersprache aus. Python und Ruby haben einige Funktionen, die von funktionalen Programmiersprachen inspiriert sind, aber Sie schreiben Code im Allgemeinen immer noch auf eine sehr zwingende Weise. (Es ähnelt C: Sie können OO-ähnlichen Code in C schreiben, aber niemand betrachtet C ernsthaft als OO-Sprache.)
Schauen Sie: Bei der funktionalen Programmierung geht es nicht nur um Lambdas oder
map
Funktionen höherer Ordnung. Es geht um Design . Ein in einer "wahren" funktionalen Programmiersprache geschriebenes Programm löst Probleme über die Zusammensetzung von Funktionen. Während Programme, die in Ruby oder Python geschrieben wurden, möglicherweise FP-ähnliche Funktionen verwenden, lesen sie sich im Allgemeinen nicht wie eine Reihe zusammengesetzter Funktionen.quelle
Jede von Ihnen erwähnte funktionale Sprache passt sehr gut in eine bestimmte Nische, und aufgrund der jeweils ermutigenden idiomatischen Muster eignen sie sich sehr gut für bestimmte Aufgaben, die in Python nicht möglich wären, wenn Sie nicht eine riesige Bibliothek von Hilfsmodulen erstellt hätten. Das offensichtlichste Beispiel für eine solche Nischenleistung ist das Erlang-Modell der Parallelität. Die anderen haben ähnliche Stärken.
quelle
Jedes Konzept, das in Lambda-Calculus, LISP und Scheme verfügbar ist, ist in Python verfügbar. Sie können also funktionale Programmierung darin durchführen. Ob es bequem ist oder nicht, ist eine Frage des Kontexts und des Geschmacks.
Sie können in Python (Ruby, Scala) problemlos einen LISP-Interpreter (oder eine andere funktionale Sprache) schreiben (was bedeutet das?). Sie können einen Interpreter für Python mit rein funktionalen Funktionen schreiben, aber es würde viel Arbeit erfordern. Sogar "funktionale" Sprachen sind heutzutage ein Multiparadigma.
Dieses alte und schöne Buch enthält die meisten (wenn auch nicht alle) Antworten darauf, was das Wesen der funktionalen Programmierung ausmacht.
quelle
eval()
Funktion, die benötigt wird, um Code in Daten umzuwandeln , aber es geht noch weiter: Sie können damit den größten Teil der Laufzeitumgebung wie in LISP ändern.eval()
ist eine Laufzeit-Metaprogrammierung. Manchmal ist es nützlich, aber es ist extrem teuer. Lisp-Makros sind unterschiedlich, es ist eine Metaprogrammierung zur Kompilierungszeit. Es ist in Python in keiner verwendbaren Form verfügbar.Denn Python kann auch in einem nicht funktionalen Stil programmieren, und das ist für den FP-Puristen nicht gut genug. Pragmatischere Programmierer können jedoch die Vorteile des funktionalen Stils genießen, ohne dogmatisch zu sein:
- John Hughes, Warum funktionale Programmierung wichtig ist
quelle
goto
ist schrecklich.call-with-current-continuation
.