Die meisten gängigen Sprachen, einschließlich objektorientierter Programmiersprachen (OOP) wie C #, Visual Basic, C ++ und Java, wurden hauptsächlich zur Unterstützung der imperativen (prozeduralen) Programmierung entwickelt, während Haskell / Gofer-ähnliche Sprachen rein funktional sind. Kann jemand näher auf den Unterschied zwischen diesen beiden Programmierarten eingehen?
Ich weiß, dass es von den Benutzeranforderungen abhängt, die Art der Programmierung zu wählen, aber warum wird empfohlen, funktionale Programmiersprachen zu lernen?
oop
functional-programming
Swapnil Kotwal
quelle
quelle
Antworten:
Definition: Eine imperative Sprache verwendet eine Folge von Anweisungen, um zu bestimmen, wie ein bestimmtes Ziel erreicht werden soll. Diese Anweisungen sollen den Status des Programms ändern, wenn jede nacheinander ausgeführt wird.
Beispiele: Java ist eine zwingende Sprache. Beispielsweise kann ein Programm erstellt werden, um eine Reihe von Zahlen hinzuzufügen:
Jede Anweisung ändert den Status des Programms, von der Zuweisung von Werten zu jeder Variablen bis zur endgültigen Addition dieser Werte. Anhand einer Folge von fünf Anweisungen wird dem Programm ausdrücklich mitgeteilt, wie die Zahlen 5, 10 und 15 addiert werden sollen.
Funktionale Sprachen: Das funktionale Programmierparadigma wurde explizit entwickelt, um einen rein funktionalen Ansatz zur Problemlösung zu unterstützen. Funktionale Programmierung ist eine Form der deklarativen Programmierung.
Vorteile reiner Funktionen: Der Hauptgrund für die Implementierung funktionaler Transformationen als reine Funktionen besteht darin, dass reine Funktionen zusammensetzbar sind: in sich geschlossen und zustandslos. Diese Eigenschaften bieten eine Reihe von Vorteilen, darunter die folgenden: Verbesserte Lesbarkeit und Wartbarkeit. Dies liegt daran, dass jede Funktion aufgrund ihrer Argumente eine bestimmte Aufgabe erfüllen soll. Die Funktion ist nicht auf einen externen Status angewiesen.
Einfachere wiederholte Entwicklung. Da der Code einfacher umzugestalten ist, sind Änderungen am Design häufig einfacher zu implementieren. Angenommen, Sie schreiben eine komplizierte Transformation und stellen dann fest, dass ein Teil des Codes in der Transformation mehrmals wiederholt wird. Wenn Sie eine reine Methode umgestalten, können Sie Ihre reine Methode nach Belieben aufrufen, ohne sich um Nebenwirkungen sorgen zu müssen.
Einfacheres Testen und Debuggen. Da reine Funktionen einfacher isoliert getestet werden können, können Sie Testcode schreiben, der die reine Funktion mit typischen Werten, gültigen Kantenfällen und ungültigen Kantenfällen aufruft.
Für OOP-Personen oder imperative Sprachen:
Objektorientierte Sprachen sind gut, wenn Sie einen festen Satz von Operationen für Dinge haben und wenn sich Ihr Code weiterentwickelt, fügen Sie hauptsächlich neue Dinge hinzu. Dies kann erreicht werden, indem neue Klassen hinzugefügt werden, die vorhandene Methoden implementieren, und die vorhandenen Klassen werden in Ruhe gelassen.
Funktionale Sprachen sind gut, wenn Sie einen festen Satz von Dingen haben und wenn sich Ihr Code weiterentwickelt, fügen Sie hauptsächlich neue Operationen für vorhandene Dinge hinzu. Dies kann erreicht werden, indem neue Funktionen hinzugefügt werden, die mit vorhandenen Datentypen rechnen und die vorhandenen Funktionen in Ruhe gelassen werden.
Nachteile:
Es hängt von den Benutzeranforderungen ab, die Art der Programmierung zu wählen. Daher kann es nur dann schaden, wenn Benutzer nicht die richtige Art der Programmierung wählen.
Wenn die Evolution in die falsche Richtung geht, haben Sie Probleme:
quelle
Hier ist der Unterschied:
Imperativ:
... und so weiter und so fort ...
Deklarativ, wovon funktional eine Unterkategorie ist:
... und so weiter und so fort ...
Zusammenfassung: In imperativen Sprachen teilen Sie dem Computer mit, wie und in welcher Reihenfolge Bits, Bytes und Wörter im Speicher geändert werden sollen. In funktionalen teilen wir dem Computer mit, was Dinge, Aktionen usw. sind. Zum Beispiel sagen wir, dass die Fakultät 0 0 ist und die Fakultät jeder anderen natürlichen Zahl das Produkt dieser Zahl und die Fakultät ihres Vorgängers ist. Wir sagen nicht: Um die Fakultät von n zu berechnen, reservieren Sie einen Speicherbereich und speichern Sie dort 1, multiplizieren Sie dann die Zahl in diesem Speicherbereich mit den Zahlen 2 bis n und speichern Sie das Ergebnis an derselben Stelle und am Ende. Der Speicherbereich enthält die Fakultät.
quelle
Die meisten modernen Sprachen sind in unterschiedlichem Maße sowohl imperativ als auch funktional. Um die funktionale Programmierung besser zu verstehen, ist es am besten, ein Beispiel für eine reine funktionale Sprache wie Haskell im Gegensatz zu imperativem Code in einer nicht so funktionalen Sprache wie Java / C # zu nehmen. Ich glaube, es ist immer einfach, dies anhand eines Beispiels zu erklären.
Funktionale Programmierung: Berechnen Sie die Fakultät von n, dh n! dh nx (n-1) x (n-2) x ... x 2 x 1
Beachten Sie, dass Haskel das Überladen von Funktionen auf die Ebene des Argumentwerts zulässt. Im Folgenden finden Sie ein Beispiel für einen imperativen Code mit zunehmendem Grad an Imperativität:
Diese Lektüre kann eine gute Referenz sein, um zu verstehen, wie sich zwingender Code mehr auf Teil, Zustand der Maschine (i in for-Schleife), Ausführungsreihenfolge und Flusskontrolle konzentriert.
Das spätere Beispiel kann grob als Java / C # Lang-Code und der erste Teil als Einschränkung der Sprache selbst im Gegensatz zu Haskell angesehen werden, um die Funktion um den Wert (Null) zu überladen, und kann daher gesagt werden, dass es sich andererseits nicht um eine puristische Funktionssprache handelt Hand kann man sagen, es unterstützt funktionale Prog. bis zu einem gewissen Grad.
Offenlegung: Keiner der oben genannten Codes wird getestet / ausgeführt, sollte aber hoffentlich gut genug sein, um das Konzept zu vermitteln. Ich würde mich auch über Kommentare für eine solche Korrektur freuen :)
quelle
return n * factorial(n-1);
?n * (n-1)
Die funktionale Programmierung ist eine Form der deklarativen Programmierung, die die Logik der Berechnung beschreibt und die Reihenfolge der Ausführung vollständig herabgesetzt wird.
Problem: Ich möchte diese Kreatur von einem Pferd in eine Giraffe verwandeln.
Jeder Artikel kann in beliebiger Reihenfolge ausgeführt werden, um das gleiche Ergebnis zu erzielen.
Imperative Programmierung ist prozedural. Staat und Ordnung sind wichtig.
Problem: Ich möchte mein Auto parken.
Jeder Schritt muss ausgeführt werden, um zum gewünschten Ergebnis zu gelangen. Das Einfahren in die Garage bei geschlossenem Garagentor würde zu einem kaputten Garagentor führen.
quelle
Funktionale Programmierung ist "Programmieren mit Funktionen", bei der eine Funktion einige erwartete mathematische Eigenschaften aufweist, einschließlich referenzieller Transparenz. Aus diesen Eigenschaften ergeben sich weitere Eigenschaften, insbesondere bekannte Argumentationsschritte, die durch Substituierbarkeit ermöglicht werden und zu mathematischen Beweisen führen (dh das Vertrauen in ein Ergebnis rechtfertigen).
Daraus folgt, dass ein Funktionsprogramm lediglich ein Ausdruck ist.
Sie können den Kontrast zwischen den beiden Stilen leicht erkennen, indem Sie die Stellen in einem Imperativprogramm notieren, an denen ein Ausdruck nicht mehr referenziell transparent ist (und daher nicht mit Funktionen und Werten erstellt wird und selbst nicht Teil einer Funktion sein kann). Die zwei offensichtlichsten Stellen sind: Mutation (z. B. Variablen) andere Nebenwirkungen nicht lokaler Kontrollfluss (z. B. Ausnahmen)
Auf diesem Rahmen von Programmen als Ausdrücken, die aus Funktionen und Werten bestehen, wird ein ganzes praktisches Paradigma von Sprachen, Konzepten, "Funktionsmustern", Kombinatoren und verschiedenen Typsystemen und Bewertungsalgorithmen aufgebaut.
Nach der extremsten Definition kann fast jede Sprache - sogar C oder Java - als funktional bezeichnet werden, aber normalerweise behalten sich die Leute den Begriff für Sprachen mit spezifisch relevanten Abstraktionen vor (wie Abschlüsse, unveränderliche Werte und syntaktische Hilfsmittel wie Mustervergleich). In Bezug auf die Verwendung der funktionalen Programmierung werden Funktionen verwendet und Code ohne Nebenwirkungen erstellt. verwendet, um Beweise zu schreiben
quelle
Der imperative Programmierstil wurde in der Webentwicklung von 2005 bis 2013 praktiziert.
Mit der imperativen Programmierung haben wir Code geschrieben, der Schritt für Schritt genau auflistet, was unsere Anwendung tun soll.
Der funktionale Programmierstil erzeugt Abstraktion durch clevere Möglichkeiten, Funktionen zu kombinieren.
In den Antworten wird die deklarative Programmierung erwähnt, und dazu möchte ich sagen, dass die deklarative Programmierung einige Regeln auflistet, denen wir folgen müssen. Wir geben dann einen so genannten Anfangszustand für unsere Anwendung an und lassen diese Regeln das Verhalten der Anwendung definieren.
Nun, diese kurzen Beschreibungen machen wahrscheinlich nicht viel Sinn. Lassen Sie uns also die Unterschiede zwischen imperativer und deklarativer Programmierung durchgehen, indem wir eine Analogie durchgehen.
Stellen Sie sich vor, wir bauen keine Software, sondern backen Kuchen, um ihren Lebensunterhalt zu verdienen. Vielleicht sind wir schlechte Bäcker und wissen nicht, wie wir einen köstlichen Kuchen so backen sollen, wie wir sollten.
Also gibt uns unser Chef eine Liste mit Anweisungen, was wir als Rezept kennen.
Das Rezept sagt uns, wie man einen Kuchen macht. Ein Rezept ist in einem imperativen Stil wie folgt geschrieben:
Das deklarative Rezept würde Folgendes bewirken:
1 Tasse Mehl, 1 Ei, 1 Tasse Zucker - Ausgangszustand
Regeln
Imperative Ansätze zeichnen sich also durch schrittweise Ansätze aus. Sie beginnen mit Schritt eins und fahren mit Schritt 2 fort und so weiter.
Sie erhalten schließlich ein Endprodukt. Wenn wir diesen Kuchen machen, nehmen wir diese Zutaten, mischen sie, legen sie in eine Pfanne und in den Ofen und Sie haben Ihr Endprodukt.
In einer deklarativen Welt ist es anders. Im deklarativen Rezept würden wir unser Rezept in zwei separate Teile aufteilen. Beginnen Sie mit einem Teil, der den Anfangszustand des Rezepts wie die Variablen auflistet. Unsere Variablen hier sind also die Mengen unserer Zutaten und ihre Art.
Wir nehmen den Ausgangszustand oder die Ausgangsbestandteile und wenden einige Regeln auf sie an.
Also nehmen wir den Ausgangszustand und durchlaufen diese Regeln immer wieder, bis wir einen essfertigen Rhabarber-Erdbeerkuchen oder was auch immer bekommen.
In einem deklarativen Ansatz müssen wir also wissen, wie diese Regeln richtig strukturiert werden.
Die Regeln, nach denen wir unsere Zutaten untersuchen oder angeben möchten, wenn sie gemischt sind, legen Sie sie in eine Pfanne.
Bei unserem Ausgangszustand stimmt das nicht überein, da wir unsere Zutaten noch nicht gemischt haben.
Regel 2 besagt also, wenn sie nicht gemischt sind, mischen Sie sie in einer Schüssel. Okay, ja, diese Regel gilt.
Jetzt haben wir eine Schüssel mit gemischten Zutaten als unseren Zustand.
Jetzt wenden wir diesen neuen Zustand wieder auf unsere Regeln an.
Regel 1 besagt also, wenn Zutaten gemischt sind, lege sie in eine Pfanne. Okay, jetzt gilt Regel 1, lass es uns tun.
Jetzt haben wir diesen neuen Zustand, in dem die Zutaten gemischt und in einer Pfanne sind. Regel 1 ist nicht mehr relevant, Regel 2 gilt nicht.
Regel 3 besagt, wenn sich die Zutaten in einer Pfanne befinden, legen Sie sie in den Ofen. Gut, dass diese Regel für diesen neuen Zustand gilt. Lassen Sie es uns tun.
Und am Ende haben wir einen köstlichen heißen Apfelkuchen oder was auch immer.
Wenn Sie wie ich sind, denken Sie vielleicht, warum wir nicht immer noch imperative Programmierung durchführen. Das macht Sinn.
Nun, für einfache Abläufe ja, aber die meisten Webanwendungen haben komplexere Abläufe, die vom imperativen Programmierdesign nicht richtig erfasst werden können.
In einem deklarativen Ansatz können wir einige Anfangsbestandteile oder einen Anfangszustand wie
textInput=“”
eine einzelne Variable haben.Möglicherweise beginnt die Texteingabe als leere Zeichenfolge.
Wir nehmen diesen Ausgangszustand und wenden ihn auf eine Reihe von Regeln an, die in Ihrer Anwendung definiert sind.
Wenn ein Benutzer Text eingibt, aktualisieren Sie die Texteingabe. Nun, im Moment trifft das nicht zu.
Wenn eine Vorlage gerendert wird, berechnen Sie das Widget.
Nun, nichts davon trifft zu, so dass das Programm nur darauf wartet, dass ein Ereignis eintritt.
Irgendwann aktualisiert ein Benutzer die Texteingabe und dann wenden wir möglicherweise Regel Nummer 1 an.
Wir können das auf aktualisieren
“abcd”
Also haben wir gerade unsere Text- und Texteingabe-Aktualisierungen aktualisiert, Regel Nr. 2 gilt nicht, Regel Nr. 3 sagt, wenn die Texteingabe aktualisiert wurde, was gerade stattgefunden hat, dann rendern wir die Vorlage erneut und kehren dann zu Regel 2 zurück, die besagt, ob die Vorlage gerendert wird , berechne das Widget, okay, lass uns das Widget berechnen.
Im Allgemeinen möchten wir als Programmierer nach deklarativeren Programmierentwürfen streben.
Der Imperativ scheint klarer und offensichtlicher zu sein, aber ein deklarativer Ansatz lässt sich für größere Anwendungen sehr gut skalieren.
quelle
• Imperative Sprachen:
Effiziente Ausführung
Komplexe Semantik
Komplexe Syntax
Parallelität ist vom Programmierer entworfen
Komplexe Tests haben keine referenzielle Transparenz und Nebenwirkungen
• Funktionssprachen:
Einfache Semantik
Einfache Syntax
Weniger effiziente Ausführung
Programme können automatisch gleichzeitig erstellt werden
Einfaches Testen, referenzielle Transparenz, keine Nebenwirkungen
quelle
Ich denke, es ist möglich, funktionale Programmierung zwingend auszudrücken:
if... else
/ oderswitch
AnweisungenEs gibt große Probleme mit einem solchen Ansatz:
Die funktionale Programmierung, die Behandlung von Funktionen / Methoden wie Objekte und die Akzeptanz von Staatenlosigkeit, wurde geboren, um die Probleme zu lösen, von denen ich glaube.
Anwendungsbeispiel: Frontend-Anwendungen wie Android, iOS oder die Logik von Webanwendungen inkl. Kommunikation mit dem Backend.
Weitere Herausforderungen bei der Simulation der funktionalen Programmierung mit imperativem / prozeduralem Code:
Ich glaube auch, dass der Funktionscode am Ende des Tages in Baugruppen- oder Maschinencode übersetzt wird, der von den Compilern zwingend / prozedural ist. Wenn Sie jedoch keine Assembly schreiben, ist die funktionale Programmierung für Menschen, die Code mit einer für Menschen lesbaren Sprache auf hoher Ebene schreiben, die geeignetere Ausdrucksweise für die aufgeführten Szenarien
quelle
Ich weiß, dass diese Frage älter ist und andere sie bereits gut erklärt haben. Ich möchte ein Beispielproblem nennen, das dasselbe in einfachen Worten erklärt.
Problem: Schreiben der 1-Tabelle.
Lösung: -
Nach imperativem Stil: =>
Nach Funktionsstil: =>
Erklärung im imperativen Stil schreiben wir die Anweisungen expliziter und können vereinfacht aufgerufen werden.
Wo wie im funktionalen Stil Dinge, die selbsterklärend sind, ignoriert werden.
quelle