Der Beispielcode von John the Statistician zeigt keine funktionale Programmierung an, da bei der funktionalen Programmierung der Schlüssel darin besteht, dass der Code KEINE ZUWEISUNGEN ausführt ( record = thingConstructor(t)
ist eine Zuweisung) und KEINE NEBENWIRKUNGEN hat ( localMap.put(record)
eine Anweisung mit Nebeneffekt). . Aufgrund dieser beiden Einschränkungen wird alles, was eine Funktion tut, vollständig von ihren Argumenten und ihrem Rückgabewert erfasst. Schreiben Sie den Code des Statistikers so um, wie er aussehen müsste, wenn Sie eine funktionale Sprache mit C ++ emulieren möchten:
RT getOrCreate (const T Sache,
const Funktion <RT <T >> thingConstructor,
const Map <T, RT <T> localMap) {.
return localMap.contains (t)?
localMap.get (t):
localMap.put (t, thingConstructor (t));
}}
Aufgrund der Regel ohne Nebenwirkungen ist jede Anweisung Teil des Rückgabewerts (daher return
steht sie an erster Stelle ), und jede Anweisung ist ein Ausdruck. In Sprachen, die die funktionale Programmierung erzwingen, ist das return
Schlüsselwort impliziert, und die if- Anweisung verhält sich wie der ?:
Operator von C ++ .
Außerdem ist alles unveränderlich, daher localMap.put
muss eine neue Kopie von localMap erstellt und zurückgegeben werden, anstatt die ursprüngliche localMap wie bei einem normalen C ++ - oder Java-Programm zu ändern . Abhängig von der Struktur von localMap kann die Kopie Zeiger auf das Original wiederverwenden, wodurch die zu kopierende Datenmenge verringert wird.
Zu den Vorteilen der funktionalen Programmierung gehört die Tatsache, dass funktionale Programme kürzer sind und es einfacher ist, ein funktionales Programm zu ändern (da keine versteckten globalen Effekte zu berücksichtigen sind), und es einfacher ist, das Programm direkt in das Programm zu integrieren erster Platz.
Funktionsprogramme werden jedoch in der Regel langsam ausgeführt (aufgrund all der zu kopierenden Aufgaben) und sie interagieren nicht gut mit anderen Programmen, Betriebssystemprozessen oder Betriebssystemen, die sich mit Speicheradressen befassen, Little-Endian Byteblöcke und andere maschinenspezifische, nicht funktionierende Bits. Der Grad der Nichtinteroperabilität korreliert tendenziell umgekehrt mit dem Grad der funktionellen Reinheit und der Strenge des Typsystems.
Die populäreren funktionalen Sprachen haben wirklich sehr, sehr strenge Typsysteme. In OCAML können Sie nicht einmal Ganzzahl- und Gleitkomma-Mathematik mischen oder dieselben Operatoren verwenden (+ dient zum Hinzufügen von Ganzzahlen, +. Zum Hinzufügen von Gleitkommazahlen). Dies kann entweder ein Vorteil oder ein Nachteil sein, je nachdem, wie sehr Sie die Fähigkeit eines Typprüfers schätzen, bestimmte Arten von Fehlern zu erkennen.
Funktionale Sprachen haben in der Regel auch sehr große Laufzeitumgebungen. Haskell ist eine Ausnahme (ausführbare GHC-Programme sind sowohl zur Kompilierungszeit als auch zur Laufzeit fast so klein wie C-Programme), aber SML-, Common Lisp- und Scheme-Programme benötigen immer Tonnen Speicher.
Why do we want successive calls to a function to yield the same result. What is the problem with the way things are in C? I never understood this.