Facebook
Twitter
Google+
Kommentare
26

Wer braucht Variablen? Die funktionale Welt …

Ich nutze gleich einmal Nils Abwesenheit (Urlaub) 😉 und verbiete Variablen, globale Zustände, globale Variablen, Schleifen und Referenzübergaben bei Funktionsaufrufen. Auch wenn sich jetzt alle Leser Nils zurückwünschen, diese Einschränkungen ergeben Sinn und ermöglichen sehr effizient zu programmieren. Machbar ist dies durch das zur imperativen Welt sehr unterschiedliche Paradigma der funktionalen Programmierung (basierend am Lambda-Kalkül), das auch immer mehr in imperativen Sprachen, wie zum Beispiel PHP, integriert wird. Neben Vorteilen, die die Programmierung vereinfachen, ist das bereits sehr alte Konzept (erste Grundlagen 1936) auch bestens für die Zukunft mit Multiprozessoren und Cloud-Computing gerüstet, da eine Parallelisierung beinahe automatisch erfolgen kann. Näheres jedoch im Laufe des Artikels.
Beginnen wir zuerst einmal mit den größten praktischen Unterschieden (zum leichteren Verständnis mit PHP Code) ganz nach dem Motto: „Alles ist eine Funktion“.

Keine Variablen? Wie kann ich dann ohne Variablen x + y rechnen, wenn z.B. x=3 und y=2?

Da wir nur Funktionen zur Verfügung haben, erstellen wir für die Addition einfach 3 Funktionen:
1. Funktion mit dem Namen x:

function x() { return 3; }

2. Funktion mit dem Namen y:

function y() { return 2; }

3. Funktion mit dem Namen +:

function plus($x,$y) { return $x + $y; }
function result() { return plus(x(),y()); }

Die Funktionen x und y sind daher Funktionen, die immer einen bestimmten konstanten Wert zurückgeben. Dieser Wert kann jedoch im Gegensatz zu Variablen nicht mehr geändert werden. Das Ergebnis result ist durch den Aufruf der Funktion plus mit den Parametern x und y definiert. Wir haben also die Berechnung ohne Variablen durchgeführt. Natürlich ist eine derartige Konstruktion in PHP nur bedingt sinnvoll, soll aber zeigen, dass der Verzicht auf Variablen auch grundsätzlich in PHP technisch möglich ist.

Keine Zustände oder globalen Variablen?

In der funktionalen Welt ist es sehr wichtig, dass Funktionen beim Aufruf mit gleichen Parametern (Input) immer den selben Wert zurückliefern (Output). Egal zu welchen Zeitpunkt im Programm oder auf welchem Rechner ausgeführt, muss eine Funktion bei einem bestimmten Input immer den selben Output haben.

$GLOBALS['einwert'] = 0;
function garNichtFunktional($x) {
  $GLOBALS['einwert'] += 1;
  return $x + $GLOBALS['einwert'];
}

Bei dieser Funktion wird bei zwei aufeinander folgenden Aufrufen nicht der selbe Rückgabewert errechnet, da sich zwischen zwei Aufrufen der globale Wert einwert ändert. So liefert garNichtFunktional(4) zuerst 5 als Ergebnis und bei einem erneuten Aufruf das Ergebnis 6. Die Funktion wird in diesem Beispiel von außen (der globalen Variable) beinflusst. Genau aus diesem Grund, um eine Abhängigkeit von einem Bereich außerhalb der Funktion zu verhindern, ist es ebenfalls nicht möglich, eine Referenz als Parameter zu übergeben. Erhält eine Funktion eine Referenz, könnte die Funktion einen Zustand/Wert außerhalb ihres Bereiches über die Referenz verändern und damit andere Funktionen bzw. Zustände beeinflussen. Diese Veränderung von Bereichen außerhalb der Funktion ist unter dem Begriff Seiteneffekte bekannt. Um Seiteneffekte zu verhindern, wird daher nur das Call-by-Value Konzept angewandt. Eine Funktion kann daher nur über die Parameter und dem Return-Wert mit der „Außenwelt“ kommunizieren.

Keine Schleifen?

Da Schleifen Zählvariablen besitzen, sind diese in strengen funktionalen Konzepten ebenfalls nicht erlaubt. Ersetzt wird die Mächtigkeit von Schleifen durch die Rekursion. Die folgende while Schleife

$x = 1;
while ($x <= 10) {
  $x += 1;
}

kann zum Beispiel rekursiv durch die folgende Funktion abgebildet werden.

function bisZehn($x) {
  if ($x >= 10) return $x;
  else return bisZehn($x+1);
}
$x = bisZehn(1);

Funktionen als Parameter?

Da es keine klassischen Variablen gibt und jeder Ausdruck als auswertbare Funktion angesehen wird, können als Parameter nur Funktionen übergeben werden. Dieses Feature (sogenannte Funktionen höherer Ordnung oder Higher-Order Functions) ist auch seit der PHP Version 5.3 vorhanden und ermöglicht zum Beispiel folgende Konstrukte:

function array_map($array,$funktion) {
  for ($i=0; $i < count($array); $i++) {
    $array[$i] = $funktion($array[$i]);
  }
  return $array;
}

//oder streng funktional ohne for Schleife mit Rekursion implementiert

function array_map($array,$funktion,$index) {
  if ($index >= count($array)) {
    return array();
  }
  return array_merge(
    array($funktion($array[$index])),
    array_map($array,$funktion,$index+1)
  );
}

array_map($mein_array,function($element) { return $element+5; },0);
array_map($mein_array,function($element) { return md5($element); },0);

Die Funktion array_map wendet dabei eine beliebige übergebene Funktion auf das übergebene Array an. Der erste Aufruf würde zum Beispiel zu jedem Element 5 addieren. Der zweite Aufruf übergibt eine anonyme Funktion, die den md5 Hash Wert für einen Parameter $element berechnet, und liefert daher als Gesamtergebnis das Array mit den md5 Hash Werten der originalen Array-Elemente.
Der große Vorteil besteht hierbei in der flexiblen Wiederverwendbarkeit der Funktion array_map. Diese kann mit beliebigen Funktionen kombiniert werden und spart viel Programmierarbeit. Natürlich ist es nicht sinnvoll in PHP streng funktional zu programmieren und keine Schleifen und Variablen mehr zu verwenden. Auch im Beispiel der Funktion array_map ist ersichtlich, dass der rein funktionale Code nicht unbedingt einfacher und verständlicher wird. Funktionale Sprachen sind dagegen für das funktionale Paradigma optimiert, wie das folgende Beispiel derselben Funktion array_map in der funktionalen Programmiersprache OCaml zeigt.

let rec array_map my_fun = function
| [ ] -> [ ]
| x::xs -> [my_fun x] @ array_map my_fun xs;;

OCaml Code Erklärung: Die | Zeilen dienen hierbei als Vergleichsstruktur (Pattern Matching) und funktionieren ähnlich wie ein switch Befehl. Ist das übergebene Array (bzw. in diesem Fall eine Liste) leer, entspricht also [ ], wird eine leere Liste zurückgegeben. Sind noch Elemente in der Liste, wird diese in das erste Element (x) und eine Restliste (xs) aufgetrennt. Auf das erste Element wird die übergebene Funktion my_fun angewandt und die Funktion array_map rekursiv mit der Restliste aufgerufen. Das Symbol @ verbindet zwei Listen und führt in dem Beispiel die resultierenden Listen der rekursiven Aufrufe zusammen. Das Ergebnis ist eine Liste, in der auf alle ursprünglichen Elemente die übergebene Funktion my_fun angewandt wurde.

Was bringts?

Bisher waren funktionale Programmiersprachen vor allem in der akademischen Welt anzutreffen, da sie der Mathematik sehr nahe stehen und daher im wissenschaftlichen Bereich oft Anwendung finden. Klassische Vertreter sind Haskell, Erlang, OCaml, Scala, Scheme, Lisp, aber auch moderne Sprachen wie zum Beispiel PHP, integrieren Features der funktionalen Welt. Einen wichtigen Beitrag zur Verbreitung hat sicher auch JavaScript geleistet, da hier stark auf funktionale Sprachkonstrukte zurückgegriffen wird.
Doch welche Vorteile ergeben sich durch die Verwendung von funktionalen Sprachen bzw. ihren Features?
Die Verwendung von Funktionen als Parameter (Higher-Order Functions) ist eine der wichtigsten Funktionalitäten, die einem das Programmierleben stark vereinfachen können. Sie sind meist wesentlich flexibler und können daher öfters im Programmcode wiederverwendet werden. Zusätzlich ist es möglich, komplexe Abläufe zu abstrahieren und dann in beliebigen Bereichen wiederzuverwenden. Dank PHP 5.3 ist das nun auch für den PHP Programmierer möglich.
Das funktionale Konzept ist auch keineswegs nur ein akademisches Hirngespinst, sondern ist seit langer Zeit auch im produktiven Einsatz (z.B. Anwendungen in der Telekommunikation mit Erlang) anzutreffen.
Ein weiterer Vorteil, der vor allem durch die starke Zunahme der Parallelrechner (Quad-Core ist bereits im Consumer-Bereich der Standard) immer wichtiger wird, ist die einfache Möglichkeit zur Parallelisierung. Da in streng funktionalen Programmiersprachen keine Seiteneffekte auftreten können, kann eine Funktion unabhängig vom restlichen Programm zum Beispiel auf einem anderen Prozessor oder Rechner ausgeführt werden. Auch Google bedient sich mit dem MapReduce Konzept (beschrieben im phphatesme Artikel …und das Leben nach SQL geht weiter … jetzt wird reduziert!) diesem Vorteil und vereinfacht so die Verteilung von Tasks (z.B. Suchindexerzeugung) über mehrere tausend Server hinweg.
Auch die laufende Integration von funktionalen Sprachfeatures in aktuellen modernen Programmiersprachen zeigt zusätzlich, dass es sich hierbei um ein gelungenes Konzept handelt, das die Programmierung stark vereinfachen kann. Eine tiefere Auseinandersetzung mit diesem Thema ist also auch für den klassischen PHP Programmierer sinnvoll und erweitert nicht nur den imperativen Tellerrand, sondern ermöglicht auch eine Verbesserung des Programmierstils bzw. Ausnützung modernen Sprachfeatures in PHP. PHPhatesme plant ebenfalls weitere Beiträge zu diesem Thema – über Anregungen und Input freuen wir uns natürlich auch in den Kommentaren.

Hier wie immer noch einige weiterführende Links:

Über den Autor

Wolfgang Gassler

Wissenschaftlicher Mitarbeiter in der Forschungsgruppe Datenbanken und Informationssysteme an der Universität Innsbruck. Web-Entwickler seit über 10 Jahren - mit PHP3 groß geworden.
Kommentare

26 Comments

  1. Cooles Thema und auch der Artikel ist schön einfach geschrieben! Würde gerne mehr lesen.

    Als Vorteil wird die einfache Parallelisierung genannt und das sehe ich ein. Soweit ich das bis jetzt weiß, ist Parallelisierung in PHP aber momentan nur auf Prozess Ebene möglich (forks) und das ist nicht ganz so schön. Gibt es in PHP doch noch eine andere Möglichkeit der Parallelisierung oder sollte das unter der Oberfläche geschehen?

    Generell kann ich die Möglichkeiten der funktionalen Programmierung noch nicht so ganz erkennen. Die Vorteile sind aber klar.

    Reply
  2. Ein paar Anmerkungen – wie immer 😉

    1) Die Übergabe der Funktions-Parameter mit Call by Value kann doch gar nicht sichergestellt werden wenn ich ein Objekt übergebe
    2) Funktionen / Methoden sollten nie Seiteneffekte haben – egal ob jetzt in der funktionalen Programmierung oder nicht. Das zu verhindern (bzw. verhindern zu können) hat doch nichts mit dem Einsatz des Programmier-Stils zu tun.
    3) Und Parallelisierung im Web (wo PHP zu 99.9% der Fälle nun einmal eingesetzt wird) erreiche ich doch relativ einfach, da jeder Request eines Users unabhängig von anderen Requests ist. Logiken innerhalb dieses Request zu parallelisieren macht doch wenig Sinn, da die Wartezeit des Nutzer dann generell viel zu groß ist.

    Reply
  3. —-
    Logiken innerhalb dieses Request zu parallelisieren macht doch wenig Sinn, da die Wartezeit des Nutzer dann generell viel zu groß ist.
    —-

    Genau das habe ich mir auch gedacht. Natürlich gibt es unterschiedliche Stile – aber ich glaube dieser hat auch folgen!

    Reply
  4. Vom Thema ganz interessant, aber aus meiner Sicht auch nur ein Weg von vielen und in den meisten Projekten sicher nicht der richtige, auch wenn die Nebenläufigkeitsvorteile sicher zu beachten sind.
    Die Vorteile des „weniger über Nebenläufigkeit nachdenken müssen“ im Gegensatz zur OO wird dafür durch mehr nachdenken bei Rekursion (die generell gut ist, aber sicher nicht immer sofort für das menschliche Hirn einfach aufzulösen) und co beseitigt.

    Naja, alles hat seine Daseinsberechtigung, ein allheilmittel ist es aus meiner Sicht nicht und sollte nur sehr bedacht in Teilbereichen eingesetzt werden.

    Reply
  5. Die einzig sinnvolle Parallelisierung die ich bei Webanwendungen sehe, ist ein einen anderen Prozess zu starten der z.B. ein einen EIntrag in einer DB macht und dann eine E-Mail an den Benutzer verschickt, während man dem Benutzer gleichzeitig schon die Website anzeigt. Padraic Brady hat dazu einiges geschrieben in 3 Teilen in seinem Blog unter http://blog.astrumfutura.com/archives/417-The-Mysteries-Of-Asynchronous-Processing-With-PHP-Part-1-Asynchronous-Benefits,-Task-Identification-and-Implementation-Methods.html

    Für mich erscheint die funktionale Programmierung den eigenen Quellcode stark zu verkomplizieren. Entsprechend müsste man ja auch mehr Unit Tests schreiben, oder nicht? Was mache ich mit dynamischen Werten, die ich z.B. aus einem Service bekomme? Verpacke ich da auch alles in eine Funktion?

    Reply
  6. @Rudi
    | Als Vorteil wird die einfache Parallelisierung genannt und das sehe ich ein. Soweit
    | ich das bis jetzt weiß, ist Parallelisierung in PHP aber momentan nur auf Prozess
    | Ebene möglich (forks) und das ist nicht ganz so schön. Gibt es in PHP doch noch
    | eine andere Möglichkeit der Parallelisierung oder sollte das unter der Oberfläche
    | geschehen?
    Parallelisierung über Messaging im Netzwerk lässt sich auch per PHP realisieren ^^

    @Ulf:
    2. Methoden haben (fast) immer Seiteneffekte. Der Grund ist, dass Methoden im Kontext einer Klasse stehen und deshalb von dessen Zustand abhängig sind, bzw ihn beeinflussen (was in diesem Fall der Seiteneffekt ist). Andersherum: Wenns keine Seiteneffekte hätte, bräuchte man die dazugehörige Klasse auch nicht und könnte es

    als Funktion implementieren.

    | Die Verwendung von Funktionen als Parameter (Higher-Order Functions) ist eine der
    | wichtigsten Funktionalitäten, die einem das Programmierleben stark vereinfachen
    | können. Sie sind meist wesentlich flexibler und können daher öfters im Programmcode
    | wiederverwendet werden. Zusätzlich ist es möglich, komplexe Abläufe zu abstrahieren
    | und dann in beliebigen Bereichen wiederzuverwenden. Dank PHP 5.3 ist das nun auch
    | für den PHP Programmierer möglich.
    Das ist falsch: Funktionen als Parameter zu übergeben, was auch vorher bereits möglich. Die Funktion war dabei zwar ein String, macht aber effektiv nur einen geringeren Unterschied 😉

    Reply
  7. @KingCrunch
    Dann lass es mich als „negative“ Seiteneffekte bezeichnen, da der Begriff ja eh sehr weitläufig ist. Natürlich ändere ich mit setter-Methoden einer Klasse deren Zustände. Aber eben auch nicht mehr. Und übergebene Objekte als Parameter sollten innerhalb dieser Methoden Ihren Zustand nie ändern (es gibt sicherlich begründete Ausnahmen, aber deren Anzahl sollte minimal bleiben). Und diese „negativen Seiteneffekte“ sollte man eben minimieren / bei 0 halten sonst bekommt man zwangsläufig irgendwann Probleme beim Refactoring / Erweitern der Anwendung.

    Reply
  8. @Ulf: In einigen funktionalen Programmiersprachen zwingt dich der Compiler dazu, deinen Code ohne Seiteneffekte, d.h. rein funktional, zu schreiben. Da so gut wie jedes brauchbare Programm jedoch Seiteneffekte enthält, gibt es Techniken, mit denen man Seiteneffekte und reine Funktionen vereinbaren kann: Monaden. Dadurch wird dem Compiler anhand der Typsignatur mitgeteilt, dass eine Funktion Seiteneffekte enthalten kann. Das hat zum einen den Vorteil, dass man sofort (möglicherweise) unsicheren Code erkennt, und zum anderen kann der Compiler diese Informationen zur Optimierung des Codes (Stream-Fusion, Parallelisierung, …) nutzen. Aus eigener Erfahrung weiß ich, dass man versuchen wird, möglichst viele Probleme rein funktional, sprich ohne Seiteneffekte, zu lösen.
    Ich kann gut verstehen, dass man denkt, dass der Code, den man jetzt schreibt, nahezu seiteneffektfrei ist, aber ich habe diesen Trugschluss erst begriffen, als mich der Compiler darauf aufmerksam gemacht hat, wie viel Code von Seiteneffekten bzw. Funktionen mit Seiteneffekten abhängt… Man sollte das nicht unterschätzen.

    @Julian: Ob man Rekursion oder Schleifen einfacher findet, hängt vor allem damit zusammen, wie stark man sich damit bereits auseinandergesetzt hat. In imperativen Programmen muss man jedes Mal im Kopf haben, dass man noch einen Zustand hat, den man ggf. nicht sieht, und der möglicherweise Seiteneffekte im Hintergrund hat. Schaue ich mir jedoch eine (rein) funktionale Rekursion an, habe ich sofort alle wichtigen Werte im Blick. Aber in einem Punkt gebe ich dir Recht: while-Schleifen sind intuitiver zu begreifen.

    @Marc: Begründung?

    @Jens: Es ist ein anderes Paradigma, das nur begrenzt zu imperativer Programmierung passt. In funktionalen Programmiersprachen gibt es häufig weder Schleifen noch Variablen, sodass man auf Rekursion setzen muss. Aber diese Sprachen haben komplett andere Voraussetzung, weshalb es in der Tat nicht sinnvoll ist, nur noch Funktionen in einer imperativen Programmiersprache zu verwenden. Es geht eher darum, dass man Ideen (wie z.B. array_map, array_reduce, array_filter) in die imperative Welt übernehmen kann. Im Grunde genommen handelt es sich wieder um Muster, mit denen man häufig wiederkehrende Probleme mit minimalem Aufwand lösen kann.

    @Dennis: Gekonnt eingesetzt wird der Code damit nicht komplizierter, sondern vor allem einfacher, kürzer und letztendlich auch weniger fehlerträchtig. Allerdings haben einige funktionale Programmiersprachen die Angewohnheit eine ungewohnte Syntax zu haben. Wenn man aus PHP jedoch eine funktionale Programmiersprache machen möchte, würde das natürlich scheitern. Verwendet man jedoch eine Sprache wie Haskell braucht man sogar noch deutlich weniger Unit-Tests, weil sehr viele Fehlerklassen bereits vom Compiler ausgeschlossen werden können. In diesem Zusammenhang habe ich mal gehört, dass 90% der Haskell-Programme, die durch den Compiler akzeptiert wurden, ordnungsgemäß funktionieren.

    Reply
  9. Interessanter Artikel, aber warum nicht das Beste aus beiden Welten (objektorientiert und funktional) verbinden?

    -> http://www.scala-lang.org/

    @Ulf
    „““3) Und Parallelisierung im Web (wo PHP zu 99.9% der Fälle nun einmal eingesetzt wird) erreiche ich doch relativ einfach, da jeder Request eines Users unabhängig von anderen Requests ist. Logiken innerhalb dieses Request zu parallelisieren macht doch wenig Sinn, da die Wartezeit des Nutzer dann generell viel zu groß ist.“““

    Einfach mal über den Tellerrand schauen, was die Globalplayer (Google, Amazon, Ebay, Yahoo, Twitter, etc.) einsetzen, ich glaube da wirst du PHP lange suchen. Ruby, Python, Java, Scala, alles Sprachen die eine wesentliche größere Bedeutung haben als PHP und nur weil jeder Wald- und Wiesenprogrammierer mit PHP anfängt, heißt das nicht, dass 99,9% PHP einsetzen.
    Ich mag PHP in den richtigen Einsatzbereichen, aber parallele Verarbeitung gehört sicher nicht dazu. Und wenn selbst Facebook mit HipHopforPHP die kritischen Anwendungsbereiche in C umwandelt, dann werden die sich dabei sicher etwas gedacht haben … 😉

    Reply
  10. Oh ja die funktionale Programmierung. Ich wurde früher auch einmal mit mosml gequält. Schade ist, dass der kleine ocaml Code nicht als PHP-variante zur Verfügung steht und ein kleiner Test gemacht wurde, ob sich der rekursive Ansatz performanzmäßig von einer Schleife unterscheidet und wie der Speicherverbrauch aussieht.

    Wie mehrfach erwähnt ist bei einer Webapplikationen die Parallelisierung auf Requestebene vorhanden. Einen Vorteil in einer fein-granulareren Parallelisierung sehe ich nicht. Ist momentan wohl eher ein Hype. Und ja, wenn ich ein gesamtes System (bspw. ejabberd) programmiere, macht es Sinn eine Programmiersprache zu nutzen, die mich auf Mehrprozessorsystemen unterstützt.

    Reply
  11. @Norbert: Ohne es getestet zu haben, kann ich dir versprechen, dass eine Rekursion in PHP langsamer ist als eine Schleife, da der Interpreter dafür einiges an Verwaltungsaufwand unternehmen muss, was bei einer Schleife nicht der Fall ist. Die Vorteile sehe ich klar an anderen Stellen.

    Reply
  12. Andre
    | @Ulf: In einigen funktionalen Programmiersprachen zwingt dich der Compiler dazu,
    | deinen Code ohne Seiteneffekte, d.h. rein funktional, zu schreiben. Da so gut wie
    | jedes brauchbare Programm jedoch Seiteneffekte enthält, gibt es Techniken, mit denen
    | man Seiteneffekte und reine Funktionen vereinbaren kann: Monaden. Dadurch wird dem
    | Compiler anhand der Typsignatur mitgeteilt, dass eine Funktion Seiteneffekte
    | enthalten kann.
    Henne-Ei 😉 Eigentlich ^muss^ jede funktionale Sprache frei von Seiteneffekten sein. Damit verbietet man aber zB das Lesen von Dateien, oder Reaktionen auf Eigenarten von Betriebssystemen etc.

    @Norbert
    | Wie mehrfach erwähnt ist bei einer Webapplikationen die Parallelisierung auf
    | Requestebene vorhanden. Einen Vorteil in einer fein-granulareren Parallelisierung
    | sehe ich nicht. Ist momentan wohl eher ein Hype.
    PHP kennt zwar keine Threads, aber ich würd sie begrüßen 😉 Wenn man dann noch PHP-Prozesse für Request dauerhaft aktiv halten kann („Worker“), könnten „übliche Werte“ (Konfiguration, ..) im Master gehalten werden, ohne jedes mal neu gelesen, oder anderweitig gecacht werden zu müssen. Das setzt aber eine gewisse Parallelisierbarkeit voraus.

    Bei Parallelisierung ist die Teilung des Arbeitsaufwandes ja nur ein Aspekt. Bei Webanwendungen kommt hinzu, dass ein Thread/Prozess auch nur einen Request bedienen kann, also gibt es erzwungenermaßen auch immer mehrere Worker. Mit bisherigen Ansatz machen diese allerdings bis zu einem gewissen Punkt — dort, wo der eigentliche Request interessant — immer das Gleiche, was man eben reduzieren könnte. Ein Master könnte nun beim (eigenen) Startup das Lesen der Konfiguration, Initialisierung, Bootstrapping (,…) übernehmen und davon ausgehend einzelne Threads starten, die alle auf die selbe Grundlage zurückgreifen und nur „den Kontext“ selbst verwalten.

    Reply
  13. Andre
    | @Norbert: Ohne es getestet zu haben, kann ich dir versprechen, dass eine Rekursion in | PHP langsamer ist als eine Schleife, da der Interpreter dafür einiges an
    | Verwaltungsaufwand unternehmen muss, was bei einer Schleife nicht der Fall ist. Die
    | Vorteile sehe ich klar an anderen Stellen.
    Verwette auch meine Katze, dass die Callstack bei PHP für viele Aufgaben viel zu klein ist. kA, wie groß der bei Haskell und co ist, aber wenn man nur auf Funktionen angewiesen ist, sollte der schon verdammt groß sein.
    Ergo: Du wirst vermutlich garnicht alles testen können 😉

    Reply
  14. Sorry aber ich muss mal was OffTopic los werden:
    ich wünsche mir für die Kommentarfunktion ein ‚Antworten‘ und eine entsprechende Kaskadierung dieser Antworten.

    Ich finde das Thema interessant und die Diskussion darüber ist es erst recht aber es ist sehr schwer den einzelnen ‚Threads‘ zu folgen….
    Also Niels: wenn Du wieder erholt bist, wär das doch was… 🙂

    Zum Thema:
    ich bin da irgendwie auch noch nicht richtig überzeúgt davon.
    Aber so wie ich Wolfgang verstanden habe, war das mit dem Variablen weg lassen nur ein provokantes Beispiel.
    Und so wie Andre schreibt, ist es meiner Meinung nach auch in PHP nicht notwendig, da es halt keine rein funktionale Sprache ist.
    Aber machbar ist es, wie man sieht… 😉

    @Wolfang:
    ich freue mich auf praktische Beispiele & um das Feature sinnvoll in PHP zu nutzen. Der Grundgedanke kam sehr gut rüber.

    Reply
  15. |Ein Master könnte nun beim (eigenen) Startup das Lesen der Konfiguration,
    |Initialisierung, Bootstrapping (,…) übernehmen und davon ausgehend einzelne
    |Threads starten, die alle auf die selbe Grundlage zurückgreifen und nur |“den Kontext” selbst verwalten.

    @KingCrunch:
    In der Java-Welt übernehmen diese Aufgaben ganz gerne die Application-Server. Wenn man die Annäherung von PHP in Richtung Java sieht, wird das sicher auch noch kommen 🙂

    Reply
  16. Hallo Wolfgang,

    super Artikel! Vielen Danke 😉

    Ein kleiner Fehler ist mir aufgefallen. Im array_map Beispiel tritt ein Fehler auf, da array_map() eine interne PHP Funktion ist. Einfach in array_mapp() umbenennen, dann klappts 😉

    Fatal error: Cannot redeclare array_map() in …

    Beste Grüße

    Andy

    Reply
  17. Macht eine reine funktionale Programmierung in PHP Sinn? NEIN, aber man kann natürlich gute Ideen und Konstrukture in php übernehmen. Die Vorteile bzgl. Parallelisierung sind natürlich nicht so eng im Sinne von PHP zu sehen, sondern allgemein von funktionalen Programmiersprachen. Alle Vorteile (noch wesentlich mehr als im Artikel erwähnt) kann man sowieso nur mit einer richtigen funktionalen Programmiersprache nutzen, da eine solche Sprache auch genau auf diese Vorteile optimiert ist.
    Auf jeden Fall sollte man neue Sprachfeatures (Higher-Order Functions, Closures, …) in PHP betrachten und wenn sinnvoll (muss jeder selbst entscheiden) auch einsetzen.

    Reply
  18. Ganz klar, dass dieses Programmierparadigma bei den meisten PHPlern auf Abneigung stößt. Besonders diejenigen, die mit Objektorientierung aufgewachsen sind, haben es sehr schwer sich in dieser Welt zurecht zu finden. Nicht umsonst wurde aber gerade die funktionale Programmierung bei uns an der Uni zu Beginn eingeführt, um den Studenten auch Blicke in andere Bereiche der Programmierung zu geben. Objektorientierung ist nicht das nec plus ultra und es ist interessant auch einmal strikte funktionale Programmierung in PHP angewandt zu sehen.
    Allerdings bin auch ich der Meinung, dass dies in PHP nicht richtig umzusetzen ist und daher nicht angewandt werden sollte. PHP verwendet automatisch Referenzübergaben im Zusammenhang mit Objekten und man tendiert ganz schnell auf Grund der Möglichkeit es anders zu lösen, sich von der funktionalen Programmierung wegzubewegen.
    Was man aber guten Gewissens übernehmen kann, um seine eigenen Codes sauberer zu halten: Funktionen sollten – egal bei welcher Eingabe – tatsächlich immer den selben Typ zurückgeben. In PHP ist hier beim Programmieren etwas aufzupassen, da man leicht mal Rückgabewerte auf Grund der Typfreiheit durcheinanderwürfelt. Hat man es sich aber einmal angewöhnt eine Funktion / Methode stets so zu programmieren, dass sie immer einen Typ (oder null zum Beispiel) zurückgibt, werden auch Fehlerbehandlungen und Zustandsprüfungen sehr viel einfacher.

    Klasse Artikel,

    Julian.

    Reply
  19. Sorry, aber das ist Schwachsinn. Man kann nicht ganz ohne Variablen auskommen. Vorallem ist es auch sinnlos. Wie greifst du ohne Variablen auf die URL-Parameter zu?

    Reply
  20. Variablen nennt man Variablen, weil ihr Inhalt variabel ist. Das ist in der funktionalen Programmierung nicht so, denn dort können die „Variablen“ (oder besser: nullstellige Funktionen) nicht verändert werden.

    Reply
  21. Konstanten sind prinzipiell Abbildungen von Namen auf Daten. Funktionen sind hingegen „Algorithmen“, weshalb man Funktionen nicht durch Konstanten ersetzen kann. Allerdings könnte man Variablen theoretisch durch Konstanten ersetzen, was allerdings einige praktische Nachteile hätte.

    Reply
  22. Ich habe vor kurzem wieder angefangen ein Websystem in PHP zu bauen und ich muss echt sagen, dass es extrem mühsam für mich ist. Ich habe die letzten Jahre nur mit höheren Programmiersprachen, C und Haskell auf der Uni programmiert. Man kann mit PHP zwar einiges im Webbereich machen, doch finde ich, dass man sich durch PHP programmierung einen unsauberen und schlechten Programmierstil aneignet. Ich bin es gewohnt schöne strukturierte abstrakte Funktionen/Klassen oder wie auch immer zu schreiben. In PHP wir schnell etwas unübersichtlich und man kann die objektorientiertheit auch leider nur begrenzt nutzen, da Generzität u.Ä Konzepte nicht unterstützt werden.

    Reply

Leave a Comment.

Link erfolgreich vorgeschlagen.

Vielen Dank, dass du einen Link vorgeschlagen hast. Wir werden ihn sobald wie möglich prüfen. Schließen