Gängige Pro­gram­mier­spra­chen lassen in der Regel ver­schie­de­ne Pro­gram­mier­pa­ra­dig­men zu, wobei grob zwischen der de­kla­ra­ti­ven Pro­gram­mie­rung und der im­pe­ra­ti­ven Pro­gram­mie­rung un­ter­schie­den wird. Bei solchen Pa­ra­dig­men handelt es sich – ver­ein­facht gesagt – um die grund­le­gen­de Her­an­ge­hens­wei­se bei der Pro­gram­mie­rung einer Software. Ein Unterform des de­kla­ra­ti­ven Ansatzes ist die so­ge­nann­te funk­tio­na­le Pro­gram­mie­rung, die ins­be­son­de­re bei der Ent­wick­lung folgender Programme bzw. Codes genutzt wird:

  • tech­ni­sche und ma­the­ma­ti­sche An­wen­dun­gen
  • Künst­li­che In­tel­li­genz (KI)
  • Compiler und Parser
  • Al­go­rith­men

Was macht den Pro­gram­mie­rungs­an­satz bzw. funk­tio­na­le Pro­gram­mier­spra­chen für diese Art von Com­pu­ter­an­wen­dun­gen so in­ter­es­sant? Und worin besteht der Un­ter­schied zu anderen Konzepten wie bei­spiels­wei­se der ob­jekt­ori­en­tier­ten Pro­gram­mie­rung?

Was ist funk­tio­na­le Pro­gram­mie­rung?

Der Name lässt es bereits vermuten: Im Mit­tel­punkt der funk­tio­na­len Her­an­ge­hens­wei­se beim Pro­gram­mie­ren stehen Funk­tio­nen. Bei einem funk­tio­na­len Programm können alle Elemente als Funktion auf­ge­fasst und der Code kann durch an­ein­an­der­ge­reih­te Funk­ti­ons­auf­ru­fe aus­ge­führt werden. Im Um­kehr­schluss gibt es keine ei­gen­stän­di­gen Zu­wei­sun­gen von Werten. Eine Funktion stellt man sich dabei am besten als besondere Variante eines Un­ter­pro­gramms vor. Dieses ist wie­der­ver­wend­bar und gibt, anders als eine Prozedur, direkt ein Resultat zurück.

Natürlich gibt es in vielen höheren Pro­gram­mier­spra­chen Funk­tio­nen, die definiert und dann an­ge­wen­det werden. Dies ist also noch nicht das Besondere an der funk­tio­na­len Pro­gram­mie­rung. Was den funk­tio­na­len Ansatz so wichtig für die In­for­ma­tik und gleich­zei­tig so viel­fäl­tig ein­setz­bar macht, ist die Tatsache, dass Funk­tio­nen innerhalb dieses Pro­gram­mier­pa­ra­dig­mas ver­schie­de­ne „Gestalten“ annehmen können. Sie können bei­spiels­wei­se – wie Daten – mit­ein­an­der verknüpft werden. Ferner ist die Ver­wen­dung als Parameter sowie die Nutzung als Funk­ti­ons­er­geb­nis möglich. Diese spezielle Be­hand­lung der Funk­tio­nen erlaubt Pro­gram­mie­rern die Im­ple­men­tie­rung und Ver­ar­bei­tung von weit­rei­chen­der Be­rech­nungs­auf­ga­ben (ins­be­son­de­re solcher von sym­bo­li­scher Natur).

Warum die funk­tio­na­le Pro­gram­mie­rung heute re­le­van­ter ist denn je

Obwohl die Wurzeln der funk­tio­na­len Pro­gram­mie­rung bis in die 1930er-Jahre zu­rück­rei­chen (als Teil der ma­the­ma­ti­schen Grund­la­gen­for­schung), erfreut sich die funk­tio­na­le Her­an­ge­hens­wei­se immer noch großer Be­liebt­heit, vor allem im tech­ni­schen und ma­the­ma­ti­schen Bereich. Dafür gibt es gleich mehrere Gründe:

  • um­fang­rei­che Mög­lich­kei­ten zur al­ge­bra­ischen Pro­gramm­trans­for­ma­ti­on
  • um­fang­rei­che Mög­lich­kei­ten zur al­ge­bra­ischen Pro­gramm­syn­the­se
  • einfache se­man­ti­sche Analyse-Mög­lich­kei­ten dank des Verzichts auf „innere Zustände im Be­rech­nungs­pro­zess“ und „Sei­ten­ef­fek­te“.
  • Wegfall innerer Zustände: Es sind, anders als bei der im­pe­ra­ti­ven Pro­gram­mie­rung, keine inneren Zustände eines Be­rech­nungs­pro­zes­ses er­for­der­lich.
  • Verzicht auf Sei­ten­ef­fek­te: Auch auf die zu den inneren Zuständen ge­hö­ren­den Zu­stands­än­de­run­gen, die so­ge­nann­ten Sei­ten­ef­fek­te, kann beim funk­tio­na­len Arbeiten ver­zich­tet werden.

Funk­tio­na­le Pro­gram­mie­rung bietet ein hohes Maß an Abs­trak­ti­on, denn sie basiert auf dem ma­the­ma­ti­schen Begriff und Prinzip der Funktion. Bei sauberer Anwendung führt diese Art des Pro­gram­mie­rens zu sehr präzisem Code. Aus möglichst vielen kleinen, wie­der­holt nutzbaren und sehr spe­zia­li­sier­ten Einheiten, den Funk­tio­nen, wird ein Programm zur Lösung einer we­sent­li­chen größeren Aufgabe erstellt.

Es gibt also zahl­rei­che prak­ti­sche Gründe, warum die funk­tio­na­le Pro­gram­mie­rung und die mit diesem Prinzip ar­bei­ten­den funk­tio­na­len Pro­gram­mier­spra­chen bis heute eine besondere Stellung innerhalb der In­for­ma­tik einnehmen, vor allem, wenn es um komplexe ma­the­ma­ti­sche Auf­ga­ben­stel­lun­gen und Al­go­rith­men geht. Gleich­zei­tig sorgen die sehr spe­zi­el­len An­wen­dungs­ge­bie­te dafür, dass funk­tio­na­le Pro­gram­mier­spra­chen so etwas wie ein Ni­schen­da­sein führen.

Auf einen Blick: Die wich­tigs­ten funk­tio­na­len Pro­gram­mier­spra­chen

Zu den wich­tigs­ten Pro­gram­mier­spra­chen, die auf dem funk­tio­na­len Ansatz basieren, zählen folgende Vertreter:

  • LISP
  • ML
  • Haskell
  • OCaml
  • F#
  • Erlang
  • Clojure
  • Scala

Darüber hinaus gibt es bekannte Pro­gram­mier­spra­chen, die die funk­tio­na­le Pro­gram­mie­rung als eines von mehreren möglichen Pa­ra­dig­men zulassen:

  • Perl
  • Ruby
  • Visual Basic .NET
  • Dylan
  • EC­MA­Script

Vor- und Nachteile funk­tio­na­ler Pro­gram­mie­rung im ta­bel­la­ri­schen Überblick

Vorteile Nachteile
Programme sind zu­stands­los Daten (z. B. Variablen) sind nicht ver­än­der­bar
Gut für die Par­al­le­li­sie­rung geeignet Abruf großer Da­ten­men­gen nicht effizient möglich
Leicht testbarer Code Nicht emp­feh­lens­wert für Ver­bin­dun­gen zu Da­ten­ban­ken und Servern
Leicht ve­ri­fi­zier­ba­rer Code, selbst zu­stands­lo­se Funk­tio­nen lassen sich ve­ri­fi­zie­ren Nicht geeignet für viele Re­kur­sio­nen desselben Stacks
Lässt sich gut mit im­pe­ra­ti­ver, ob­jekt­ori­en­tier­ter Pro­gram­mie­rung kom­bi­nie­ren Rekursive Pro­gram­mier­wei­se kann zu schwer­wie­gen­den Fehlern führen
Prä­zi­se­rer, kürzerer Code Nicht für alle Aufgaben geeignet

Die Tabelle gibt einen guten Überblick darüber, ob das funk­tio­na­le Paradigma der passende Ansatz für die Pro­gram­mie­rung eines Soft­ware­pro­jekts ist oder nicht. Die Ent­schei­dung zugunsten eines Pro­gram­mier­stils ist häufig aber auch stark von den per­sön­li­chen Vorlieben des Ent­wick­lers abhängig. So steht bei vielen Pro­gram­mie­rern bei­spiels­wei­se auch die ob­jekt­ori­en­tier­te Pro­gram­mie­rung als konkrete Al­ter­na­ti­ve zur funk­tio­na­len Her­an­ge­hens­wei­se hoch im Kurs. Im Folgenden sollen die beiden Ansätze daher kurz mit­ein­an­der ver­gli­chen werden – inklusive ab­schlie­ßen­dem Praxis-Beispiel.

Trend oder kein Trend? Ob­jekt­ori­en­tier­te und funk­tio­na­le Pro­gram­mie­rung im Quer­ver­gleich

Genau wie in der Mode gibt es auch beim Pro­gram­mie­ren Trends: Seit geraumer Zeit ist das ob­jekt­ori­en­tier­te Pro­gram­mie­ren – ins­be­son­de­re bei der Ent­wick­lung von Web­an­wen­dun­gen und Com­pu­ter­spie­len – ziemlich populär. Im Vergleich zur funk­tio­na­len Pro­gram­mie­rung be­schreibt man bei diesem Ansatz die einzelnen Elemente nicht als Funktion, sondern als Objekte und Klassen. In Kom­bi­na­ti­on mit einem Ver­er­bungs­sys­tem hat dies den Vorteil, dass sich sämtliche Kom­po­nen­ten jederzeit und pro­blem­los wie­der­ver­wen­den und erweitern lassen. Funk­tio­na­ler Code ist auf der anderen Seite we­sent­lich schlanker, über­sicht­li­cher und ins­be­son­de­re dort im Vorteil, wo testbarer und ve­ri­fi­zier­ba­rer Code benötigt wird.

Im Übrigen muss prin­zi­pi­ell gar nicht unbedingt die Wahl zwischen ob­jekt­ori­en­tier­ter und funk­tio­na­ler Pro­gram­mie­rung getroffen werden: Viele moderne Pro­gram­mier­spra­chen un­ter­stüt­zen nämlich die Arbeit mit beiden Pro­gram­mier­sti­len, sodass sich diese bequem mit­ein­an­der kom­bi­nie­ren lassen und man von den Vorzügen beider Pa­ra­dig­men pro­fi­tie­ren kann.

Funk­tio­na­le Pro­gram­mie­rung am Beispiel eines Parsers

Parser sind zentrale Elemente für die Vielzahl aller Com­pu­ter­pro­gram­men. Als Vor­ar­bei­ter für Compiler, die Pro­gram­mier­spra­che in Ma­schi­nen­spra­che über­set­zen, sind sie häufig un­ab­ding­bar.

Ein Parser lässt sich grund­sätz­lich auf Basis ver­schie­dens­ter Pro­gram­mier­pa­ra­dig­men umsetzen – bei­spiels­wei­se auch mit einer ob­jekt­ori­en­tier­ten Sprache. Der funk­tio­na­le Ansatz bietet al­ler­dings eine Reihe von nütz­li­chen Vorteilen, wenn es um die Code-Ge­stal­tung eines Parsers geht:

  • Es gibt keine globalen und ver­än­der­ba­ren Variablen. Ent­spre­chend gibt es auch keine Pro­gram­mier­feh­ler, die aus dem so­ge­nann­ten „mutable global state“ (dt. frei „Code-weiter, ver­än­der­ba­rer Zustand“) re­sul­tie­ren, wie es bei ob­jekt­ori­en­tier­ten Projekte der Fall sein kann. Davon pro­fi­tiert ein Parser als zentrales Pro­gramm­ele­ment.
  • Dank Funk­tio­nen höherer Ordnung und dem über­schau­ba­ren Pro­gramm­code lassen sich auch größere Da­ten­samm­lun­gen einfach be­wäl­ti­gen. Dies kommt einem Parser, der na­tur­ge­mäß große Da­ten­men­gen ver­ar­bei­ten muss, sehr zugute.
  • Ein Parser ist ein Pro­gramm­ele­ment, das sehr häufig durch­lau­fen wird. Es hilft also dem Ge­samt­pro­gramm, wenn dieses zentrale Element präzise pro­gram­miert wird und ent­spre­chend effizient abläuft, wie es bei der funk­tio­na­len Pro­gram­mie­rung der Fall ist.
  • Ein Fehler im Parsing-Prozess ist in der Regel fatal und muss möglichst vermieden werden. Während ein Programm läuft, entstehen aber zwangs­läu­fig zahl­rei­che se­man­ti­sche Ab­hän­gig­kei­ten, die – al­ler­dings oft erst nach längerer Laufzeit – zu schweren Fehlern führen können. Sauber umgesetzt kann funk­tio­na­le Pro­gram­mie­rung dabei helfen, solche schweren Fehler in der Aus­füh­rung zu mi­ni­mie­ren be­zie­hungs­wei­se ganz zu ver­hin­dern.
Zum Hauptmenü