Prozedurale vs. Funktionale Programmierung

Tags:

Für mich war Prozedur (procedure) immer ein Synonym für Funktion (function). Und ich denke, grundsätzlich ist das auch absolut korrekt. Der Ausdruck Funktion kommt aus der Mathematik und dort liefert eine Funktion für eine bestimme Eingabe immer die gleiche Ausgabe. In der Programmierung ist dies nicht immer der Fall: Die Funktion kann äussere Einflüsse haben (z.B. globale Variablen oder Zufallszahlen). Diese Einflüsse nennt man die Nebenwirkung (side effects) einer Funktion. Der Ausdruck Prozedur beschreibt im Gegensatz dazu einfach eine Liste von Instruktionen und muss auch keinen Rückgabewert haben.

f1(x) = 2(x + 3)
f2(x) = 2x + 6

Das sind zwei verschiedene Prozeduren, aber die gleiche Funktion. Die Instruktionen, die zur Anwendung benötigt werden, sind unterschiedlich, die Funktion ist aber dieselbe; beide Prozeduren führen mit der selben Eingabe zum selben Ergebnis.

function f1($x) { $x += 3; $x *= 2; return $x; }
function f2($x) { $x *= 2; $x += 6; return $x; }
var_dump(f1(5) === f2(5)); // true

Aber ihr seht schon, in vielen Programmiersprachen ist diese Unterscheidung wässrig und kontextabhängig.

Worauf ich aber eigentlich hinaus wollte, ist, dass mich diese Similarität stets verwirrte, wenn es um den Unterschied zwischen funktionaler und prozeduraler Programmierung ging. Dabei geht es um etwas weitaus Fundamentaleres: Verschiedene Programmierparadigmen. Also Ansätze, wie man Probleme löst.

Prozedurale Programmierung

Prozedurale Programmierung ist das, was wohl die meisten von uns mit Programmierung in Verbindungen bringen. C, C++ und Java haben sie bekannt gemacht - auch PHP nutzt sie.

Der Quellcode wird von oben nach unten gelesen und abgearbeitet. Es handelt sich also um Listen von Instruktionen. Auch Klassen und Funktionen ändern daran nichts: Es wird zwar im Quelltext "umhergesprungen", die Instruktionen werden aber immer noch sequenziell definiert und verarbeitet. C++ und Java sind also nicht nur Objekt-orientierte, sondern auch prozedurale Programmiersprachen.

Prozedurale Programmiersprachen sind auch immer imperative Programmiersprachen. Sie befehlen Linie für Linie was der Compiler/Interpreter tun soll. Diese Anweisungen oft auch den Zustand (state) des Programmes. Zum Beispiel wird eine Variable inkrementiert oder es werden Elemente aus einem Array entfernt. Solche Berechnungen sind zustandsbehaftet (stateful). Das Gegenteil dazu ist zustandslos (stateless), doch dazu später mehr.

Imperative Programmierung beschreibt wie etwas berechnet werden soll. "Gib mir alle Zahlen zwischen 1 und 100. Für jede Zahl: Überprüfe ob sie durch 7 teilbar ist und wenn ja, zeige sie auf dem Bildschirm an."

Der Maschinencode, in welchen unsere Programme von Compilern/Interpretern übersetzt werden, ist übrigens auch prozedural.

Funktionale Programmierung

In funktionalen Programmsprachen definiert man Funktionen. Ha! Und zwar ganz im mathematischen Sinne. Das Wichtige dabei ist, dass diese Funktionen ihre Eingabeparameter und den Zustand des Programmes nicht verändern - es gibt also keine Nebenwirkung, das System ist zustandslos (Um es noch etwas komplizierter zu machen: Eine Funktion kann ihren eigenen Zustand verändert - nur nicht den von anderen Bereichen des Programmes). Wenn a = b ist, müssen auch f1(a) = f1(b) und f2(a) = f2(b) sein. Dadurch sind solche Programmiersprachen ideal wenn Nebenläufigkeit (concurrency) erwünscht ist, da mehrere Instanzen des Programmes unabhängig voneinander ausgeführt werden können.

Wenn ich hier in der Theorie von funktionaler Programmierung schwadroniere, meine ich rein (pure) funktionale Programmierung. Viele Programmiersprachen sind zwar funktional, aber nicht nur (impure). Das liegt daran, dass z.B. das Ausgeben von Text an STDOUT bereits stateful, bzw. imperativ ist. Oder anders gesagt: Die Funktion print hat Nebenwirkung.

Ach ja, natürlich können Funktionen andere Funktionen aufrufen; auch sich selbst. Rekursion ist sogar extrem wichtig und präsent in der funktionalen Programmierung. Denn so wird zum Beispiel Iteration gelöst. Eine Liste (ein Array in PHP Jargon) wird an eine Funktion übergeben, die nimmt sich das erste Element und übergibt den Rest der Liste wieder an sich selber. Wenn sie eine leere Liste erhält, hört sie auf.

Als Programmierer schreibt man also Funktionen. Das Hauptprogramm an sich ist eigentlich auch eine Funktion, die dann andere Funktionen aufruft.

Rein funktionale Programmiersprachen sind auch immer deklarative Programmiersprachen.

Deklarative Programmierung beschreibt was berechnet werden soll. SQL ist eine deklarative Sprache: Man beschreibt was man als Resultat erhalten möchte, den Lösungsweg sucht die Programmiersprache selbstständig. "Ich brauche alle Zahlen zwischen 1 und 100, die durch 7 teilbar sind."

Da Funktionen ein Mittel der Mathematik sind, sind funktionale Programmiersprachen in akademischen Kreisen sehr beliebt und weit verbreitet. Bekannte Beispiele sind Haskell, LISP (bzw. seine verschiedenen Dialekte wie Scheme oder CommonLisp) oder Erlang. Zur Zeit kommen auch einige Programmiersprachen in Mode, die mehrere Programmierparadigmen vereinen. So ist Scala z.B. eine sowohl funktionale, als auch objekt-orientierte Programmiersprache. Oder dann gibt es Clojure, was ein LISP-Dialekt ist, der in der Java Virtual Machine (JVM) läuft.

Fazit

Ich hoffe ich konnte einen kurzen Überblick über funktionale Programmierung verschaffen. Zur Zeit versuche ich mich in dieser zu vertiefen, da ich mir dadurch ganz neue Denkansätze erhoffe, wie man Probleme lösen kann.

Ich freue mich über Kommentare! :)

Ähnliche Artikel

Kommentare