it-swarm.com.de

Was ist der Unterschied zwischen funktionalen und imperativen Programmiersprachen?

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 erklären, was ist der Unterschied zwischen diesen beiden Arten der Programmierung? 

Ich weiß, dass es von den Benutzeranforderungen abhängt, welche Art der Programmierung gewählt wird. Warum wird es jedoch empfohlen, funktionale Programmiersprachen zu lernen?

114
Swapnil Kotwal

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 der Reihe nach ausgeführt wird.

Beispiele: Java ist eine zwingende Sprache. Zum Beispiel kann ein Programm erstellt werden, um eine Reihe von Zahlen hinzuzufügen:

 int total = 0;
 int number1 = 5;
 int number2 = 10;
 int number3 = 15;
 total = number1 + number2 + number3; 

Jede Anweisung ändert den Status des Programms von der Zuweisung von Werten zu jeder Variablen bis zur endgültigen Addition dieser Werte. Mit einer Folge von fünf Anweisungen wird dem Programm explizit gesagt, wie die Zahlen 5, 10 und 15 zusammen addiert werden sollen.

Funktionale Sprachen: Das Paradigma der funktionalen Programmierung wurde explizit erstellt, um einen rein funktionalen Ansatz zur Problemlösung zu unterstützen. Die 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 zusammengesetzt werden können, dh in sich geschlossene und zustandslose. Diese Eigenschaften bringen eine Reihe von Vorteilen mit sich, darunter die folgenden: Verbesserte Lesbarkeit und Wartbarkeit. Dies liegt daran, dass jede Funktion mit ihren Argumenten eine bestimmte Aufgabe ausführen soll. Die Funktion ist nicht auf einen externen Zustand angewiesen.

Einfachere reiterative Entwicklung. Da der Code leichter umgestaltet werden kann, sind Änderungen am Entwurf oft einfacher zu implementieren. Nehmen Sie beispielsweise an, Sie schreiben eine komplizierte Transformation und stellen dann fest, dass sich Code in der Transformation mehrmals wiederholt. Wenn Sie durch eine reine Methode umgestalten, können Sie Ihre reine Methode nach Belieben aufrufen, ohne sich über Nebenwirkungen Gedanken machen 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 Edge-Fällen und ungültigen Edge-Fällen aufruft.

Für OOP Personen oder Imperative Sprachen:

Objektorientierte Sprachen sind gut, wenn Sie über festgelegte Operationen verfügen und bei der Weiterentwicklung Ihres Codes hauptsächlich neue Dinge hinzufügen. Dies kann durch Hinzufügen neuer Klassen erreicht werden, die vorhandene Methoden implementieren, und die vorhandenen Klassen bleiben in Ruhe.

Funktionale Sprachen sind gut, wenn Sie eine feste Anzahl von Dingen haben und während sich Ihr Code weiterentwickelt, fügen Sie in erster Linie neue Vorgänge zu vorhandenen Dingen hinzu. Dies kann durch Hinzufügen neuer Funktionen erreicht werden, die mit vorhandenen Datentypen rechnen, und die vorhandenen Funktionen werden nicht ausgeführt.

Nachteile:

Es hängt von den Benutzeranforderungen ab, die Art der Programmierung zu wählen, so dass nur dann Schaden entsteht, wenn Benutzer nicht die richtige Methode wählen.

Wenn die Evolution falsch läuft, haben Sie Probleme:

  • Das Hinzufügen einer neuen Operation zu einem objektorientierten Programm erfordert möglicherweise das Bearbeiten vieler Klassendefinitionen, um eine neue Methode hinzuzufügen 
  • Das Hinzufügen eines neuen Elements zu einem funktionalen Programm erfordert möglicherweise die Bearbeitung vieler Funktionsdefinitionen, um einen neuen Fall hinzuzufügen.
121
user2102654

Hier ist der Unterschied:

Imperativ:

  • Start
  • Schalten Sie Ihre Schuhe Größe 9 1/2 ein.
  • Machen Sie Platz in Ihrer Tasche, um eine Reihe von Schlüsseln aufzubewahren.
  • Stecken Sie die Schlüssel in den Raum für die Schlüssel in die Tasche.
  • Garage betreten.
  • Garage öffnen.
  • Auto betreten.

... und so weiter und weiter ...

  • Legen Sie die Milch in den Kühlschrank.
  • Halt.

Deklarativ, wovon funktional eine Unterkategorie ist:

  • Milch ist ein gesundes Getränk, es sei denn, Sie haben Probleme, Laktose zu verdauen.
  • Normalerweise lagert man Milch im Kühlschrank.
  • Ein Kühlschrank ist eine Box, in der die Dinge kühl bleiben.
  • Ein Geschäft ist ein Ort, an dem Artikel verkauft werden.
  • Mit "verkaufen" meinen wir den Austausch von Dingen gegen Geld.
  • Auch das Tauschen von Geld gegen Dinge wird "Kaufen" genannt.

... und so weiter und so weiter ...

  • Stellen Sie sicher, dass wir Milch im Kühlschrank haben (wenn wir sie brauchen - für faule Funktionssprachen).

Zusammenfassung: In imperativen Sprachen teilen Sie dem Computer mit, wie er Bits, Bytes und Wörter in seinem Speicher und in welcher Reihenfolge ändern kann. In funktionalen Fällen sagen wir dem Computer, was Dinge, Aktionen usw. sind. Zum Beispiel sagen wir, dass die Fakultät von 0 gleich 1 ist und die Fakultät jeder anderen natürlichen Zahl das Produkt dieser Zahl und der Fakultät des 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 Nummer 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.

192
Ingo

Funktionale Programmierung ist eine Form der deklarativen Programmierung, die die Logik der Berechnung beschreibt und die Ausführungsreihenfolge vollständig herabgesetzt ist.

Problem: Ich möchte diese Kreatur von einem Pferd in eine Giraffe verwandeln.

  • Hals verlängern
  • Beine verlängern
  • Flecken anwenden
  • Gib der Kreatur eine schwarze Zunge
  • Pferdeschwanz entfernen

Jeder Artikel kann in beliebiger Reihenfolge ausgeführt werden, um dasselbe Ergebnis zu erzielen.

Imperative Programmierung ist prozedural. Zustand und Ordnung ist wichtig.

Problem: Ich möchte mein Auto parken.

  1. Beachten Sie den Ausgangszustand des Garagentors
  2. Halten Sie das Auto in der Einfahrt an
  3. Wenn das Garagentor geschlossen ist, öffnen Sie das Garagentor. ansonsten weiter
  4. Auto in die Garage ziehen
  5. Garagentor schließen

Jeder Schritt muss ausgeführt werden, um das gewünschte Ergebnis zu erzielen. Das Einfahren in die Garage bei geschlossenem Garagentor führt zum Zerreißen des Garagentors.

7
Jakub Keller

Die meisten modernen Sprachen sind in unterschiedlichem Maße sowohl zwingend als auch funktional, aber um die funktionale Programmierung besser zu verstehen, ist es am besten, ein Beispiel für eine reine Funktionssprache wie Haskell im Gegensatz zu imperativem Code in nicht so funktionaler Sprache wie Java/c # zu nehmen. Ich glaube, es ist immer leicht, es anhand von Beispielen zu erklären. 

Funktionsprogrammierung: Berechnen Sie die Fakultät von n. d.h. n x (n-1) x (n-2) x ... x 2 x 1

-- | Haskell comment goes like
-- | below 2 lines is code to calculate factorial and 3rd is it's execution  

factorial 0 = 1
factorial n = n * factorial (n - 1)
factorial 3

-- | for brevity let's call factorial as f; And x => y shows order execution left to right
-- | above executes as := f(3) as 3 x f(2) => f(2) as 2 x f(1) => f(1) as 1 x f(0) => f(0) as 1  
-- | 3 x (2 x (1 x (1)) = 6

Beachten Sie, dass Haskel das Überladen von Funktionen auf die Ebene des Argumentwerts zulässt. Nun folgt ein Beispiel für einen imperativen Code mit zunehmendem Imperativitätsgrad: 

//somewhat functional way
function factorial(n) {
  if(n < 1) {
     return 1;
  }
  return n * factorial(n-1);   
}
factorial(3);

//somewhat more imperative way
function imperativeFactor(n) {
  int f = 1
  for(int i = 1; i <= n; i++) {
     f = f * i
  }
  return f;
}

Diese Lese kann eine gute Referenz sein, um zu verstehen, wie sich der zwingende Code mehr auf den Teil, den Zustand der Maschine (i in for-Schleife), die Ausführungsreihenfolge und die Flusssteuerung konzentriert. 

Das spätere Beispiel kann grob als Java/c # lang-Code und erster Teil als Einschränkung der Sprache selbst betrachtet werden, im Gegensatz zu Haskell, um die Funktion durch den Wert (null) zu überladen, und daher kann gesagt werden, dass es sich nicht um eine puristische Funktionssprache handelt Hand kann man sagen, dass es funktionale Prog unterstützt. bis zu einem gewissen Grad.

Disclosure: 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 zu solchen Korrekturen freuen :) 

7
old-monk

Funktionale Programmierung ist "Programmierung mit Funktionen", wobei eine Funktion einige erwartete mathematische Eigenschaften einschließlich der referenziellen Transparenz besitzt. Aus diesen Eigenschaften fließen weitere Eigenschaften, insbesondere bekannte Denkschritte, die durch Substituierbarkeit ermöglicht werden, die zu mathematischen Beweisen führen (d. H. Rechtfertigen der Zuverlässigkeit eines Ergebnisses).

Daraus folgt, dass ein funktionales Programm nur ein Ausdruck ist.

Sie können den Kontrast zwischen den beiden Stilen leicht erkennen, indem Sie die Stellen in einem imperativen Programm notieren, an denen ein Ausdruck nicht mehr referenziell transparent ist (und daher nicht aus Funktionen und Werten besteht und nicht selbst Teil einer Funktion sein kann). Die zwei naheliegendsten Stellen sind: Mutation (z. B. Variablen) Andere Nebenwirkungen Nichtlokaler Steuerungsfluss (z. B. Ausnahmen).

In diesem Rahmen von Programmen und Ausdrücken, die sich aus Funktionen und Werten zusammensetzen, ist ein praktisches Paradigma aus 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. Normalerweise behalten die Leute den Begriff jedoch für Sprachen mit spezifisch relevanten Abstraktionen (wie etwa Closures, unveränderliche Werte und syntaktische Hilfsmittel wie Pattern Matching). Was die Verwendung der funktionalen Programmierung anbelangt, so umfasst dies die Verwendung von Funktinen und die Erstellung von Code ohne Nebeneffekte, die zum Erstellen von Beweisen verwendet werden

4
Romil pawar

Imperativer Programmierstil wurde von 2005 bis 2013 in der Webentwicklung geübt.

Bei der imperativen Programmierung haben wir Schritt für Schritt Code geschrieben, in dem genau aufgeführt ist, was unsere Anwendung tun soll.

Der funktionale Programmierstil erzeugt Abstraktion durch clevere Kombinationsmöglichkeiten von Funktionen.

In den Antworten wird die deklarative Programmierung erwähnt, und ich möchte sagen, dass in der deklarativen Programmierung einige Regeln aufgeführt sind, die wir befolgen sollten. Wir stellen dann unserer Bewerbung einen so genannten Anfangszustand zur Verfügung und lassen diese Regeln definieren, wie sich die Anwendung verhält.

Nun, diese kurzen Beschreibungen machen wahrscheinlich nicht viel Sinn, also gehen wir die Unterschiede zwischen imperativer und deklarativer Programmierung durch, indem sie eine Analogie durchlaufen.

Stellen Sie sich vor, wir bauen keine Software, sondern backen Kuchen für Ihren Lebensunterhalt. Vielleicht sind wir schlechte Bäcker und wissen nicht, wie man einen leckeren Kuchen so backt, wie wir es sollten.

Unser Chef gibt uns eine Liste mit Anweisungen, was wir als Rezept wissen.

Das Rezept zeigt uns, wie man eine Torte macht. Ein Rezept ist in einem imperativen Stil geschrieben:

  1. Mischen Sie 1 Tasse Mehl
  2. 1 Ei hinzufügen
  3. Fügen Sie 1 Tasse Zucker hinzu
  4. Gießen Sie die Mischung in eine Pfanne
  5. Stellen Sie die Pfanne 30 Minuten lang in den Ofen.

Das deklarative Rezept würde folgendes tun:

1 Tasse Mehl, 1 Ei, 1 Tasse Zucker - Anfangszustand

Regeln

  1. Wenn alles gemischt ist, in die Pfanne legen.
  2. Wenn alles ungemischt ist, in eine Schüssel geben.
  3. Wenn alles in der Pfanne ist, in den Ofen stellen.

Imperative Ansätze sind also durch schrittweise Ansätze gekennzeichnet. Sie beginnen mit Schritt 1 und fahren mit Schritt 2 usw. fort.

Sie haben schließlich ein Endprodukt. Wenn Sie diese Torte herstellen, nehmen wir diese Zutaten, mischen sie, geben sie in eine Pfanne und in den Ofen, und Sie haben Ihr Endprodukt erhalten.

In einer deklarativen Welt ist es anders. Im deklarativen Rezept würden wir unser Rezept in zwei separate Teile aufteilen, beginnend mit einem Teil, der den Anfangszustand des Rezeptes wie die Variablen auflistet. Unsere Variablen sind hier also die Mengen unserer Zutaten und deren Typ.

Wir nehmen den Ausgangszustand oder die Ausgangsbestandteile und wenden einige Regeln darauf an.

Also nehmen wir den Anfangszustand und gehen sie durch diese Regeln immer wieder hindurch, bis wir einen essbaren Rhabarber-Erdbeertorte oder was auch immer bekommen.

In einem deklarativen Ansatz müssen wir also wissen, wie diese Regeln richtig strukturiert werden.

Die Regeln, die wir vielleicht prüfen sollten, um unsere Zutaten zu untersuchen, oder die Angabe, wenn sie gemischt werden, geben Sie sie in eine Pfanne.

In unserem ursprünglichen Zustand stimmt das nicht überein, weil wir unsere Zutaten noch nicht gemischt haben.

Regel 2 besagt, wenn sie nicht gemischt werden, mischen Sie sie in einer Schüssel. Okay, ja, diese Regel gilt.

Jetzt haben wir eine Schüssel mit gemischten Zutaten als Zustand.

Jetzt wenden wir diesen neuen Zustand erneut auf unsere Regeln an.

Regel 1 besagt, wenn Zutaten gemischt werden, lege sie in eine Pfanne. Okay, jetzt gilt Regel 1, lass es uns tun.

Jetzt haben wir diesen neuen Zustand, wo die Zutaten gemischt und in einer Pfanne sind. Regel 1 ist nicht mehr relevant, Regel 2 gilt nicht.

Regel 3 sagt, wenn sich die Zutaten in einer Pfanne befinden, legen Sie sie in den Ofen. Diese Regel gilt für diesen neuen Zustand. Lassen Sie uns das tun.

Und wir bekommen einen leckeren heißen Apfelkuchen oder was auch immer.

Nun, wenn Sie wie ich sind, denken Sie vielleicht, warum machen wir nicht immer noch Imperative Programmierung? Das macht Sinn.

Für einfache Flows ja, aber die meisten Webanwendungen haben komplexere Flows, die vom imperativen Programmierdesign nicht richtig erfasst werden können.

Bei einem deklarativen Ansatz haben wir möglicherweise einige Anfangsbestandteile oder einen Anfangszustand wie textInput=“”, eine einzelne Variable.

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.

  1. Wenn ein Benutzer Text eingibt, aktualisieren Sie die Texteingabe. Nun, das trifft jetzt nicht zu.

  2. Wenn eine Vorlage gerendert wird, berechnen Sie das Widget.

  3. Wenn textInput aktualisiert wird, rendern Sie die Vorlage erneut.

Nun, nichts davon trifft zu, also wartet das Programm nur auf ein Ereignis.

Irgendwann aktualisiert ein Benutzer die Texteingabe, und dann können wir die Regelnummer 1 anwenden.

Wir können das auf “abcd” aktualisieren

Wir haben also gerade unsere Text- und TextInput-Aktualisierungen aktualisiert. Die Regel Nr. 2 gilt nicht. Regel Nr. 3 gibt an, ob die Texteingabe Aktualisierung ist, was gerade geschehen ist. Dann wird die Vorlage erneut gerendert, und wir kehren zu Regel 2 zurück, die besagt, dass die Vorlage gerendert wird , berechnet das Widget, okay, lässt sich das Widget berechnen.

Im Allgemeinen wollen wir als Programmierer nach deklarativeren Programmierdesigns streben.

Imperativ scheint klarer und offensichtlicher zu sein, aber ein deklarativer Ansatz lässt sich sehr gut für größere Anwendungen skalieren.

1
Daniel

Ich denke, es ist möglich, funktionale Programmierung auf zwingende Weise auszudrücken:
- Verwendung vieler Statusprüfungen von Objekten und if... else/switch-Anweisungen
- Einige Zeitüberschreitungs-/Wartungsmechanismen, um auf Asynchronität zu achten 

Es gibt riesige Probleme mit einem solchen Ansatz:
- Regeln/Verfahren werden wiederholt - Statefulness lässt Chancen für Nebenwirkungen/Fehler

Funktionale Programmierung, die Funktionen/Methoden wie Objekte behandelt und Staatenlosigkeit umarmen, ist zur Lösung dieser Probleme geboren. 

Anwendungsbeispiele: Frontend-Anwendungen wie Android, iOS oder Web-Apps Kommunikation mit dem Backend

0
ericn