Ich habe einige Texte über deklarative / funktionale Programmierung (Sprachen) gelesen, Haskell ausprobiert und selbst einen geschrieben. Nach allem, was ich gesehen habe, hat die funktionale Programmierung gegenüber dem klassischen imperativen Stil mehrere Vorteile:
- Staatenlose Programme; Keine Nebenwirkungen
- Parallelität; Spielt sich sehr gut mit der aufstrebenden Multi-Core-Technologie
- Programme sind normalerweise kürzer und in einigen Fällen leichter zu lesen
Die Produktivität steigt (Beispiel: Erlang)
Imperative Programmierung ist ein sehr altes Paradigma (soweit ich weiß) und möglicherweise nicht für das 21. Jahrhundert geeignet
Warum sind Unternehmen, die in funktionalen Sprachen geschrieben oder programmiert sind, immer noch so "selten"?
Warum verwenden wir bei der Betrachtung der Vorteile der funktionalen Programmierung immer noch zwingende Programmiersprachen?
Vielleicht war es 1990 zu früh dafür, aber heute?
functional-programming
Pankrax
quelle
quelle
Antworten:
Denn all diese Vorteile sind auch Nachteile.
In realen Programmen dreht sich alles um Nebenwirkungen und Mutationen. Wenn der Benutzer eine Taste drückt, möchte er, dass etwas passiert. Wenn sie etwas eingeben, möchten sie, dass dieser Status den Status ersetzt, der früher vorhanden war. Wenn Jane Smith in der Buchhaltung heiratet und ihren Namen in Jane Jones ändert, sollte sich die Datenbank, die den Geschäftsprozess unterstützt, der ihren Gehaltsscheck druckt, besser mit dieser Art von Mutation befassen. Wenn Sie das Maschinengewehr auf den Außerirdischen abfeuern, modellieren die meisten Menschen dies nicht mental als den Bau eines neuen Außerirdischen mit weniger Trefferpunkten. Sie modellieren dies als Mutation der Eigenschaften eines vorhandenen Außerirdischen.
Wenn die Konzepte der Programmiersprache grundsätzlich gegen die zu modellierende Domäne arbeiten, ist es schwierig, die Verwendung dieser Sprache zu rechtfertigen.
Das Problem wird nur herumgeschubst. Mit unveränderlichen Datenstrukturen haben Sie eine günstige Thread-Sicherheit auf Kosten der möglichen Arbeit mit veralteten Daten. Mit veränderlichen Datenstrukturen haben Sie den Vorteil, dass Sie immer an neuen Daten arbeiten müssen, ohne komplizierte Logik schreiben zu müssen, um die Daten konsistent zu halten. Es ist nicht so, dass einer von ihnen offensichtlich besser ist als der andere.
Außer in den Fällen, in denen sie länger und schwerer zu lesen sind. Zu lernen, wie man Programme liest, die in einem funktionalen Stil geschrieben sind, ist eine schwierige Fähigkeit. Menschen scheinen Programme viel besser als eine Reihe von Schritten zu verstehen, die wie ein Rezept zu befolgen sind, als als eine Reihe von Berechnungen, die durchgeführt werden müssen.
Die Produktivität muss stark steigen, um die massiven Kosten für die Einstellung von Programmierern zu rechtfertigen, die wissen, wie man in einem funktionalen Stil programmiert.
Und denken Sie daran, Sie möchten kein funktionierendes System wegwerfen. Die meisten Programmierer erstellen keine neuen Systeme von Grund auf neu, sondern warten vorhandene Systeme, von denen die meisten in nicht funktionierenden Sprachen erstellt wurden. Stellen Sie sich vor, Sie versuchen dies gegenüber den Aktionären zu rechtfertigen. Warum haben Sie Ihr bestehendes Lohn- und Gehaltsabrechnungssystem verschrottet, um ein neues zu bauen, das Millionen von Dollar kostet? "Weil funktionale Programmierung großartig ist" wird die Aktionäre wahrscheinlich nicht begeistern.
Auch die funktionale Programmierung ist sehr alt. Ich sehe nicht, wie das Alter des Konzepts relevant ist.
Versteh mich nicht falsch. Ich liebe funktionale Programmierung, ich bin diesem Team beigetreten, weil ich helfen wollte, Konzepte aus der funktionalen Programmierung in C # zu bringen, und ich denke, dass Programmierung in einem unveränderlichen Stil der Weg der Zukunft ist. Die Programmierung in einem funktionalen Stil ist jedoch mit enormen Kosten verbunden , die nicht einfach wegzuwünschen sind. Der Übergang zu einem funktionaleren Stil wird über Jahrzehnte hinweg langsam und schrittweise erfolgen. Und genau das wird es sein: eine Verlagerung hin zu einem funktionaleren Stil, keine umfassende Berücksichtigung der Reinheit und Schönheit von Haskell und der Aufgabe von C ++.
Ich baue Compiler, um meinen Lebensunterhalt zu verdienen, und wir setzen definitiv auf einen funktionalen Stil für die nächste Generation von Compiler-Tools. Das liegt daran, dass die funktionale Programmierung grundsätzlich gut zu den Problemen passt, mit denen wir konfrontiert sind. Bei unseren Problemen geht es darum, Rohdaten - Zeichenfolgen und Metadaten - aufzunehmen und in verschiedene Zeichenfolgen und Metadaten umzuwandeln. In Situationen, in denen Mutationen auftreten, wie z. B. wenn jemand die IDE eingibt, eignet sich der Problembereich von Natur aus für Funktionstechniken wie das schrittweise Neuerstellen nur der Teile des Baums, die sich geändert haben. Viele Domains haben diese netten Eigenschaften nicht, die sie offensichtlich für einen funktionalen Stil zugänglich machen .
quelle
Masterminds of Programming: Gespräche mit den Machern der wichtigsten Programmiersprachen
quelle
Die Standardantwort lautet, dass keiner den anderen ersetzen wird oder sollte - es handelt sich um unterschiedliche Tools mit unterschiedlichen Vor- und Nachteilen, und welcher Ansatz den Vorteil hat, hängt vom Projekt und anderen "weichen" Problemen wie dem verfügbaren Talentpool ab.
Ich denke, Sie haben Recht, dass das Wachstum der Parallelität aufgrund von Multi-Core den Prozentsatz (der globalen Reihe von Entwicklungsprojekten) erhöht, wenn die funktionale Programmierung anderen Stilen vorgezogen wird.
Ich denke, das ist heute selten, weil der Großteil des heutigen professionellen Talentpools mit imperativen und objektorientierten Technologien am besten vertraut ist. Zum Beispiel habe ich mehr als einmal Java als Sprache für ein kommerzielles Projekt gewählt, weil es gut genug und unumstritten war und ich weiß, dass mir nie die Leute ausgehen werden, die darin (gut genug) programmieren können.
quelle
Trotz der Vorteile der funktionalen Programmierung wird die imperative und objektorientierte Programmierung niemals vollständig verschwinden.
Imperative und objektorientierte Programmierung ist eine schrittweise Beschreibung des Problems und seiner Lösung. Als solches kann es einfacher zu verstehen sein. Die funktionale Programmierung kann etwas unklar sein.
Letztendlich hat ein nützliches Programm immer Nebenwirkungen (z. B. die Bereitstellung der tatsächlichen Ausgabe für den Benutzer zum Verbrauch), sodass die reinste funktionale Sprache von Zeit zu Zeit immer noch einen Weg in die imperative Welt finden muss.
Der aktuelle Stand der Technik ist, dass imperative Sprachen (wie C #) Merkmale aus der Funktionswelt (wie Lambda-Aussagen) ausleihen und umgekehrt.
quelle
Hat es nicht?
Smalltalk war damals ein großartiges objektorientiertes System. Warum hat die objektorientierte Programmierung nicht übernommen? Nun, das hat es. Es sieht einfach nicht nach Smalltalk aus. Mainstream-Sprachen werden mit C ++, Java, C # usw. immer kleiner. Mode und Stil ändern sich langsamer als alles andere. Als OO zum Mainstream wurde, haben wir Teile von OO auf alte Sprachen geklebt, sodass sie so aussahen, als ob C sie schlucken könnte .
Funktional ist der gleiche Weg. Haskell war eine großartige funktionale Sprache. Aber wir haben heute noch mehr Mainstream-Programmierer, die C-ähnliche Syntax verwenden als vor 20 Jahren. Es muss also wie C aussehen. Fertig: Sehen Sie sich einen LINQ-Ausdruck an und sagen Sie mir, dass er nicht funktioniert.
quelle
dynamic
. Das ist die kleinste dieser Funktionen, daher ist es für mich keine Überraschung, dass sie nur in der neuesten Version der modernsten dieser drei Sprachen vorhanden ist. :-)Ich glaube, dass imperative Sprachen nur deshalb häufiger vorkommen, weil mehr Menschen daran gewöhnt sind. Weder die funktionale Programmierung noch das imperative Programmiermodell sind dunkler oder akademischer als das andere. In der Tat sind sie Ergänzungen.
Ein Poster sagte, dass imperativer Code leichter zu verstehen ist als funktionaler Programmiercode. Dies gilt nur, wenn der Leser bereits imperativen Code gesehen hat, insbesondere wenn die vorherigen Beispiele Teil derselben "Familie" sind (z. B. C / C ++, Perl, PHP und Java). Ich würde nicht behaupten, dass es für eine imperative Sprache gilt; Nehmen Sie einen Vergleich von Java und Forth, um ein extremes Beispiel zu geben.
Für einen Laien sind alle Programmiersprachen nicht entzifferbar, außer vielleicht die ausführlichen Sprachen wie Hypertalk und SQL. (Bemerkenswerterweise ist SQL eine deklarative und / oder funktionale Sprache und erfreut sich enormer Beliebtheit.)
Wenn wir von Anfang an in einer Lisp-y- oder Haskell-y-Sprache geschult worden wären, würden wir alle denken, dass funktionale Programmiersprachen völlig normal sind.
quelle
Sie haben bereits genug Antworten erhalten, dass ich nur ein paar Dinge erwähne, die ich noch nicht erwähnt habe.
In erster Linie haben prozedurale Sprachen (meiner Meinung nach) stark von ihrem Grad an Gemeinsamkeit profitiert. Zum Beispiel kann fast jeder, der fast jede der gängigen prozeduralen (oder OO-) Sprachen in fast jedem Maße kennt, die meisten anderen einigermaßen gut lesen. Ich vermeide es aktiv, in Java, C #, Cobol, Fortran oder Basic zu arbeiten (für nur einige Beispiele), kann sie aber einigermaßen gut lesen - fast genauso gut wie Menschen, die sie jeden Tag benutzen.
Auf der funktionalen Seite ist das viel weniger wahr. Zum Beispiel kann ich Scheme auch recht vernünftig schreiben, aber das nützt wenig beim Lesen von Ocaml oder Haskell (nur für ein paar Beispiele). Selbst innerhalb einer einzelnen Familie (z. B. Schema vs. Common Lisp) scheint sich die Vertrautheit mit der einen nicht annähernd so gut auf die andere zu übertragen.
Die Behauptung, dass Funktionscode besser lesbar ist, trifft nur unter einem engen Bereich von Bedingungen zu. Für Leute, die mit der Sprache sehr vertraut sind, ist die Lesbarkeit in der Tat ausgezeichnet - aber für alle anderen ist sie oft so gut wie nicht vorhanden. Schlimmer noch, während Unterschiede in prozeduralen Sprachen größtenteils syntaktisch sind und daher relativ leicht zu erlernen sind, sind Unterschiede in funktionalen Sprachen oft viel grundlegender, so dass sie ein beträchtliches Studium erfordern, um sie wirklich zu verstehen (z. B. zu wissen, dass Lisp für das Verständnis von Monaden wenig hilfreich ist).
Der andere wichtige Punkt ist, dass die Idee, dass funktionale Programme kürzer als prozedurale sind, häufig eher auf Syntax als auf Semantik basiert. In Haskell geschriebene Programme (zum Beispiel) sind oft recht kurz, aber ihre Funktionsfähigkeit ist nur ein kleiner Teil davon. Sehr viel, wenn es einfach so ist, dass Haskell eine relativ knappe Syntax hat.
Nur wenige rein funktionale Sprachen können mit APL gut um knappen Quellcode konkurrieren (obwohl APL fairerweise auch die Erstellung von Funktionen auf höherer Ebene unterstützt, ist dies also kein großer Unterschied wie in einigen anderen Fällen). Im Gegensatz dazu können Ada und C ++ (für nur einige Beispiele) in Bezug auf die Anzahl der Operationen, die zur Ausführung einer bestimmten Aufgabe erforderlich sind, durchaus wettbewerbsfähig sein, aber die Syntax ist (zumindest normalerweise) wesentlich ausführlicher.
quelle
Keine wahrgenommene Notwendigkeit
Ich erinnere mich an die Antwort meines alten Chefs Rick Cline, als ich ihm eine Kopie von John Backus 'Turing Award-Vortrag mit dem Titel Kann Programmierung vom von Neumann-Stil befreit werden?
Seine Antwort: „Vielleicht sind einige von uns nicht will , von dem von - Neumann - Stil befreit werden!“
quelle
Funktional ist für einige Dinge besser und für andere schlechter, so dass es niemals "übernimmt". Es ist jedoch in der realen Welt bereits allgegenwärtig.
Zustandslose Programme sind einfacher zu testen. Dies wird heute allgemein geschätzt und in der Industrie häufig genutzt.
Sie verbinden Gleichzeitigkeit und Parallelität.
Parallelität kann mithilfe von CSP (Communicating Sequential Processes) effektiv durchgeführt werden. Der Code in einem CSP kann seinen lokalen Status ändern, aber die zwischen ihnen gesendeten Nachrichten sollten immer unveränderlich sein.
Rein funktionale Programmierung spielt mit Multicore extrem schlecht, weil sie so cache-unfreundlich ist. Kerne konkurrieren um gemeinsam genutzten Speicher und parallele Programme werden nicht skaliert.
Scala wird oft als funktionale Sprache angesehen, ist aber nicht funktionaler als C #, eine der beliebtesten Sprachen der Welt.
Rein funktionale Programmierung hat viele schwerwiegende Nachteile, daher verwenden wir unreine funktionale Sprachen wie Lisp, Scheme, SML, OCaml, Scala und C #.
quelle
Wenn ich darüber nachdenke, was funktionale Programmierung für meine Projekte bei der Arbeit bedeuten könnte, werde ich immer auf den gleichen Weg geführt:
Um die vollen Vorteile der funktionalen Programmierung nutzen zu können, benötigen Sie Faulheit. Ja, es gibt strenge funktionale Sprachen, aber die wirklichen Vorteile der funktionalen Programmierung kommen im strengen Code nicht so gut zur Geltung. In Haskell ist es beispielsweise einfach, eine Folge von verzögerten Vorgängen für eine Liste zu erstellen, diese zu verketten und auf eine Liste anzuwenden. Z.B.
op1 $ op2 $ op3 $ op4 $ someList
. Ich weiß, dass es nicht die gesamte Liste erstellen wird, und intern bekomme ich nur eine schöne Schleife, die nacheinander durch die Elemente geht. Auf diese Weise können Sie wirklich modularen Code schreiben. Die Schnittstelle zwischen zwei Modulen kann die Übergabe potenziell großer Datenstrukturen beinhalten, und dennoch muss die Struktur nicht resident sein.Wenn Sie jedoch faul sind, ist es schwierig, über die Speichernutzung nachzudenken. Durch Ändern der Haskell-Compiler-Flags wird häufig die von einem Algorithmus verwendete Speichermenge von O (N) auf O (1) geändert, außer manchmal nicht. Dies ist nicht wirklich akzeptabel, wenn Sie Anwendungen haben, die den gesamten verfügbaren Speicher maximal nutzen müssen, und es ist selbst für Anwendungen, die nicht den gesamten Speicher benötigen, nicht besonders gut.
quelle
Zwei Dinge:
quelle