Startbild Wandflächen Berechnung
Vie­le Bei­trä­ge über funk­tio­na­le Pro­gram­mie­rung kon­zen­trie­ren sich all­zu sehr auf Kern­fea­tures von funk­tio­na­len Spra­chen. Über die tat­säch­li­chen prak­ti­schen Vor­tei­le die­ses Pro­gram­mier­pa­ra­dig­mas und deren Grün­de — die im Kern sehr ein­fach sind — wird sehr wenig geschrieben.

Die­ser Arti­kel erklärt die Moti­va­ti­on für die Ent­wick­lung funk­tio­na­ler Spra­chen, geht auf die kon­kre­ten Pro­ble­me vie­ler aktu­ell ver­brei­te­ter Spra­chen ein, beschreibt Lösungs­an­sät­ze funk­tio­na­ler Pro­gram­mie­rung und lie­fert Grün­de für deren prak­ti­sche Ver­wen­dung in allen Bereichen.

Abs­tract

Die Pro­ble­me vie­ler moder­ner Pro­gram­mier­spra­chen sind die­sel­ben, wie die Pro­ble­me der ers­ten Hoch­spra­chen. Das liegt dar­an, dass sich das Grund­kon­zept die­ser Spra­chen trotz eines gestie­ge­nen Abs­trak­ti­ons­gra­des nicht geän­dert hat. 

Funk­tio­na­le Pro­gram­mier­spra­chen wur­den ent­wi­ckelt, um die­se spä­tes­tens seit Ende der 1970er Jah­re bekann­ten Pro­ble­me zu lösen. Das Pro­gram­mier­pa­ra­dig­ma führt zu weni­ger kom­ple­xen Pro­gram­men, les­ba­rem, ver­ständ­li­chen Code und effi­zi­en­ter Ent­wick­lung. Weil die Lösung die­ser Pro­ble­me erst durch die Ent­fer­nung von der Vor­gangs­wei­se des Pro­zes­sors mög­lich wird, ist es not­wen­dig, Kon­trol­le über maschi­nen­na­he Vor­gän­ge an den Com­pi­ler abzu­ge­ben. Das erschwert bestimm­te Per­for­mance­op­ti­mie­run­gen und macht die Ver­wen­dung von Gar­ba­ge Collec­tion notwendig.

Alte Pro­ble­me moder­ner Sprachen

Als John Bac­kus in sei­ner Turing Award Lec­tu­re 1977 von der Not­wen­dig­keit eines neu­en Pro­gram­mier­pa­ra­dig­mas sprach, kri­ti­sier­te er unter ande­rem die fol­gen­den Pro­ble­me klas­si­scher (impe­ra­ti­ver) Sprachen:

  1. Spra­chen wer­den immer kom­ple­xer, aber kaum ausdrucksstärker
  2. Seman­ti­sche Aus­sa­gen sind eng mit inter­nen Zustands­än­de­run­gen verbunden
  3. Pro­gram­me haben kei­ne nütz­li­chen mathe­ma­ti­schen Eigenschaften
  4. Es feh­len Mecha­nis­men, um Pro­gram­me effi­zi­ent kom­bi­nie­ren zu können

Den Grund für die­se Pro­ble­me sah Bac­kus vor allem in der star­ken Anleh­nung klas­si­scher Spra­chen an die Kon­zep­te der Von-Neu­mann-Pro­zes­sor­ar­chi­tek­tur — er nennt die­se Spra­chen des­halb Von-Neu­mann-Spra­chen. Bac­kus ver­trat die Mei­nung, dass es zu enor­men Vor­tei­len füh­ren wür­de, eine Spra­che zu ent­wi­ckeln, die sich stär­ker von der Funk­ti­ons­wei­se des Pro­zes­sors abgrenzt.

Moder­ne impe­ra­ti­ve oder objekt­ori­en­tier­te Spra­chen lösen die von Bac­kus kri­ti­sier­ten Pro­ble­me nicht. Sie ver­bes­sern bestimm­te Aspek­te exis­tie­ren­der Spra­chen, ohne sich die­sen grund­sätz­li­chen Pro­ble­men zu stellen.

Wie­so ist eine stär­ke­re Abgren­zung von der Von-Neu­mann-Archi­tek­tur erstrebenswert?

Ein Bericht der Denk­fa­brik RAND, die 1987 im Rah­men eines For­schungs­pro­jek­tes für die DAR­PA durch­ge­führt wur­de, unter­sucht die Ursa­che für die Schwie­rig­kei­ten der Pro­gram­mie­rung in Von-Neumann-Sprachen.

“Often the asser­ti­on is made that pro­grams in von Neu­mann lan­guages like For­tran, Pas­cal or C are dif­fi­cult so syn­the­si­ze, ana­ly­ze, modi­fy or extend. While the asser­ti­on appears to be cor­rect, usu­al argu­ments given in its sup­port are not very convincing.”

Der Bericht kommt zum Schluss, dass Von-Neu­mann-Spra­chen die Pro­gram­mie­rung schwie­rig machen, weil sie kei­ne Aus­sa­gen der Form “Berech­ne jede der Funk­tio­nen f1(x), …, fn(x) für das­sel­be x” zulas­sen. Der Grund dafür ist, dass in Von-Neun­mann-Spra­chen ein belie­bi­ges Regis­ter des Pro­zes­sors (bzw. ein Bereich im Spei­cher oder eine Varia­ble) jeder­zeit über­schrie­ben wer­den kann. Es kann also nicht garan­tiert wer­den, dass die Argu­men­te einer Funk­ti­on nicht durch die Anwen­dung der Funk­ti­on ver­än­dert werden.

Das Haupt­pro­blem von klas­si­schen Pro­gram­mier­spra­chen sind also ver­än­der­ba­re Varia­blen und ver­än­der­ba­re Funk­ti­ons­ar­gu­men­te, die es unmög­lich machen, Funk­tio­nen so zu behan­deln, wie es mit mathe­ma­ti­schen Funk­tio­nen intui­tiv sinn­voll ist. Es ist nicht garan­tiert, dass das Ergeb­nis der­sel­ben Funk­ti­on, mit den­sel­ben Argu­men­ten bei mehr­ma­li­ger Aus­füh­rung das­sel­be Ergeb­nis zurückgibt.

Die­se Eigen­schaft macht Pro­gram­me in klas­si­schen Spra­chen kom­plex und schwer zu ver­ste­hen und führt zu den von Bac­kus zuvor beschrie­be­nen Pro­ble­men. Das gilt heu­te genau­so für moder­ne impe­ra­ti­ve Spra­chen, wie zum Zeit­punkt des Berich­tes von RAND für For­tran, Pas­cal oder C.

Ein funk­tio­na­les Pro­gramm ist eine Sequenz von Funktionsapplikationen

Funk­tio­na­le Spra­chen lösen genau die­ses Pro­blem der Unvor­her­seh­bar­keit von Funk­tio­nen. Sie erzwin­gen Funk­tio­nen ohne Sei­ten­ef­fek­te, erlau­ben kei­ne Ver­än­de­rung von Funk­ti­ons­ar­gu­men­ten und Varia­blen und ermög­li­chen so ein zuver­läs­si­ges, vor­her­seh­ba­res Ver­hal­ten von Funktionen.

Alle zen­tra­len Vor­tei­le funk­tio­na­ler Spra­chen erge­ben sich direkt oder indi­rekt aus die­sem Kon­zept. Es ist des­halb von zen­tra­ler Bedeu­tung, die direk­ten Aus­wir­kun­gen davon zu ver­ste­hen. Das Ergeb­nis einer Funk­ti­on ist durch ihre Argu­men­te immer ein­deu­tig bestimmt — das Ergeb­nis ist nicht vom Wert irgend­ei­ner Varia­ble (weil es kei­ne ver­än­der­ba­ren Varia­blen gibt) abhän­gig. Das führt direkt zu einer Rei­he von Vorteilen:

  • Ein­fach­heit und Ver­ständ­lich­keit: Der Ablauf eines funk­tio­na­len Pro­gram­mes ist sehr line­ar und dadurch intui­tiv leich­ter ver­ständ­lich. Man kann sich den Ablauf eines funk­tio­na­len Pro­gram­mes ein­fach als den Fluss von Daten durch Funk­tio­nen vorstellen.
  • Gra­tis loo­se Cou­pling: Solan­ge die Funk­ti­ons­si­gna­tur sich nicht ändert, kann eine Funk­ti­on belie­big ver­än­dert wer­den, ohne dass dadurch außer­halb der Funk­ti­on Pro­ble­me ent­ste­hen kön­nen. Eine Funk­ti­on kann immer durch eine belie­bi­ge Funk­ti­on mit der glei­chen Signa­tur ersetzt wer­den. Die­se Eigen­schaft macht nicht nur Refac­to­ring unglaub­lich ein­fach, son­dern führt auch zu einer sehr hohen Wie­der­ver­wend­bar­keit von Funktionen.
  • Kom­bi­nier­bar­keit: Wie in der Mathe­ma­tik ent­steht durch die Hin­ter­ein­an­der­aus­füh­rung von Funk­tio­nen eine neue Funk­ti­on. Die­ses Kon­zept ist eben­so ein­fach wie mächtig.

Pro­ble­me

Durch den höhe­ren Abs­trak­ti­ons­grad funk­tio­na­ler Spra­chen ist es not­wen­dig, Kon­trol­le über maschi­nen­na­he Vor­gän­ge an den Com­pi­ler abzu­ge­ben. Das erschwert bestimm­te Per­for­mance­op­ti­mie­run­gen und macht in der Regel die Ver­wen­dung von Gar­ba­ge Collec­tion notwendig.

Zusam­men­ge­fasst

Funk­tio­na­le Pro­gram­mie­rung löst vie­le Pro­ble­me klas­si­scher Spra­chen und macht Soft­ware­ent­wick­lung pro­duk­ti­ver. Mög­li­che Per­for­man­cen­ach­tei­le sind für die meis­ten Anwen­dungs­ge­bie­te nicht rele­vant und wer­den durch die effi­zi­en­te Aus­nüt­zung von meh­re­ren Pro­zes­sor­ker­nen wei­ter aus­ge­gli­chen. Der letz­te ent­schei­den­de Schritt in Rich­tung pro­duk­ti­ver Pro­gram­mie­rung wur­de in den 1950er Jah­ren mit der Ent­wick­lung von FOR­TRAN und der Ver­brei­tung der ers­ten Hoch­spra­chen getan. Pro­ble­me die­ser Spra­chen wur­den — vor allem von FOR­TRANS Haupt­ent­wick­ler — bald erkannt und führ­ten zur Ent­wick­lung der funk­tio­na­len Pro­gram­mie­rung. Wegen damals schlech­te­rer Per­for­mance konn­te sich die­ses Para­dig­ma nicht flä­chen­de­ckend durch­set­zen. Dass die meis­ten heu­te eta­blier­ten Spra­chen nach wie vor von FORTRAN
abstam­men, hat also vor allem his­to­ri­sche Grün­de. Mit FOR­TRANS Para­dig­ma über­neh­men moder­ne impe­ra­ti­ve Spra­chen auch des­sen grund­le­gen­de Pro­ble­me, die nicht durch inkre­men­tel­le Ver­bes­se­run­gen beho­ben wer­den kön­nen. Der nächs­te Schritt in Rich­tung pro­duk­ti­ver Pro­gram­mie­rung ist die flä­chen­de­cken­de Ver­brei­tung von funk­tio­na­ler Pro­gram­mie­rung. Für Anwen­dungs­ge­bie­te, in der bereits heu­te Spra­chen mit Gar­ba­ge-Collec­tion ver­wen­det wer­den, bringt die Ver­wen­dung funk­tio­na­ler Spra­chen enor­me Vor­tei­le bei prak­tisch kei­nen Nachteilen.

Klas­si­sche Pro­gram­mier­spra­chen: “Wie kön­nen wir Assem­bler (dann For­tran, dann C usw.) verbessern?”
Funk­tio­na­le Pro­gram­mie­rung: “Wie wür­de eine Spra­che aus­se­hen, in der Pro­gram­mie­rung ein­fach ist?”

Wir set­zen auf F#

Des­halb set­zen wir bei allen unse­ren Pro­jek­ten auf funk­tio­na­le Pro­gram­mie­rung. Die Spra­che unse­rer Wahl ist dabei — aus vie­len Grün­den — F#.

F# Logo
GDPR Cookie Consent mit Real Cookie Banner