Das wird sich aber bald ändern. Immer mehr FP-Konzepte werden in Sprachen wie Java und Python integriert . Und modernere Sprachen wie Haskell sind voll funktionsfähig. Einfache funktionale Programmierung
Dies ist dann die Erstellung von Funktionen für die Arbeit mit unveränderlichen Variablen. Im Gegensatz dazu ist objektorientierte Programmierung, wenn ein relativ konstanter Satz von Funktionen verwendet wird und der Programmierer hauptsächlich damit beschäftigt ist, vorhandene Variablen zu ändern und neue zu erstellen.
FP eignet sich naturgemäß zur Lösung dringender Probleme wie Datenanalyse und maschinelles Lernen . Dies bedeutet nicht, dass Sie sich von der objektorientierten Programmierung verabschieden und vollständig zur funktionalen Programmierung wechseln müssen. Für den modernen Programmierer ist es einfach nützlich, die Grundprinzipien von FP zu kennen, die es ihm ermöglichen, diese Prinzipien dort anzuwenden, wo sie ihm gut dienen können.
Bei der funktionalen Programmierung geht es darum, Nebenwirkungen zu beseitigen
Um die Prinzipien der funktionalen Programmierung zu verstehen, müssen Sie zunächst verstehen, was eine "Funktion" ist. Es mag langweilig erscheinen, aber am Ende können Sie sehen, was auf den ersten Blick nicht wahrnehmbar ist. Sprechen wir also über Funktionen.
Eine Funktion ist in einfachen Worten eine Entität, die eine an sie übergebene Eingabe in Ausgabedaten konvertiert, die an den Ort des Aufrufs zurückgegeben werden. In der Tat sieht nicht immer alles so einfach aus. Schauen Sie sich die folgende Python-Funktion an:
def square(x):
return x*x
Diese Funktion ist sehr einfach. Es braucht ein Argument,
xdas wahrscheinlich vom Typ intund vielleicht vom Typ floatoder ist double, und gibt das Ergebnis der xQuadrierung zurück.
Und hier ist eine andere Funktion:
global_list = []
def append_to_list(x):
global_list.append(x)
Auf den ersten Blick scheint es, dass es
xeinen Typ akzeptiert und nichts zurückgibt, da es keinen Ausdruck enthält return. Aber lassen Sie uns nicht zu Schlussfolgerungen springen!
Die Funktion kann nicht normal arbeiten, wenn die Variable nicht im Voraus deklariert wurde
global_list. Das Ergebnis dieser Funktion ist eine geänderte Liste, die in gespeichert ist global_list. Obwohl es global_listnicht als Wert deklariert ist, der an die Eingabe einer Funktion übergeben wird, ändert sich diese Variable nach dem Aufruf der Funktion.
append_to_list(1)
append_to_list(2)
global_list
Nach einigen Aufrufen der Funktion aus dem vorherigen Beispiel
global_listist die Liste keine leere Liste mehr, sondern eine Liste [1,2]. Dies erlaubt uns zu sagen, dass die Liste tatsächlich der Wert ist, der an die Eingabe der Funktion geliefert wird, obwohl dies in keiner Weise festgelegt ist, wenn die Funktion deklariert wird. Dies kann ein Problem sein.
Unehrlichkeit bei der Erklärung von Funktionen
Diese impliziten Eingabe- oder Ausgabewerte haben einen offiziellen Namen: Nebenwirkungen. Wir verwenden hier sehr einfache Beispiele, aber in komplexeren Programmen können Nebenwirkungen zu echten Komplikationen führen .
Überlegen Sie, wie Sie die Funktion testen würden
append_to_list. Es wird nicht ausreichen, die erste Zeile seiner Deklaration zu lesen und herauszufinden, dass sie getestet werden muss, indem ein Wert übergeben wird x. Stattdessen müssen Sie den gesamten Funktionscode lesen, herausfinden, was genau dort passiert, eine Variable deklarieren global_listund dann die Funktion testen. Was in unserem einfachen Beispiel anscheinend keine besonderen Schwierigkeiten verursacht, sieht in Programmen, die aus Tausenden von Codezeilen bestehen, völlig anders aus.
Glücklicherweise ist das oben genannte Problem leicht zu beheben. Sie müssen nur ehrlich sein, wenn Sie angeben, was genau zum Eingang der Funktion gehen soll. Die nächste Version unserer Funktion sieht viel besser aus als die vorherige:
newlist = []
def append_to_list2(x, some_list):
some_list.append(x)
append_to_list2(1,newlist)
append_to_list2(2,newlist)
newlist
Wir haben an diesem Code nicht viel geändert. Als Ergebnis der Operation der Funktion in
newlist, wie zuvor in global_list, stellt sich heraus [1,2], und alles andere sieht genauso aus wie zuvor.
Wir haben jedoch eine wesentliche Änderung an diesem Code vorgenommen. Wir haben die Nebenwirkungen beseitigt. Und das ist sehr gut.
Nachdem wir nun die erste Zeile der Funktionsdeklaration gelesen haben, wissen wir genau, mit welchen Eingabedaten sie arbeiten. Wenn sich das Programm nicht wie erwartet verhält, können Sie daher problemlos jede darin enthaltene Funktion testen und die Funktion finden, die nicht ordnungsgemäß funktioniert. Reine Funktionen sind einfacher zu warten.
Funktionale Programmierung schreibt reine Funktionen
Eine Funktion, die, wenn sie deklariert wird, klar anzeigt, was sie benötigt und was sie zurückgibt, ist eine Funktion ohne Nebenwirkungen. Eine Funktion ohne Nebenwirkungen ist eine reine Funktion.
Hier ist eine sehr einfache Definition der funktionalen Programmierung. Dies ist das Schreiben von Programmen, die nur aus reinen Funktionen bestehen. Reine Funktionen ändern niemals die an sie übergebenen Daten, sie erstellen nur neue und geben sie zurück. (Beachten Sie, dass ich im vorherigen Beispiel ein wenig geschummelt habe. Es ist im Geiste der funktionalen Programmierung geschrieben, aber darin modifiziert die Funktion die globale Variablenliste. Aber hier untersuchen wir nur die Grundprinzipien von FP, weshalb ich genau das getan habe. Wenn Sie wollen, können Sie es hier finde strengere Beispiele für reine Funktionen.)
Wenn Sie mit reinen Funktionen arbeiten, können Sie außerdem erwarten, dass diese, die dieselben Daten wie die Eingabe empfangen, immer dieselbe Ausgabe generieren. Und Funktionen, die nicht rein sind, können von einer Art globaler Variablen abhängen. Infolgedessen können sie bei gleicher Eingabe je nach Wert der globalen Variablen unterschiedliche Ergebnisse erzielen. Diese Tatsache kann das Debuggen und die Wartung des Codes erheblich erschweren.
Es gibt eine einfache Faustregel, um Nebenwirkungen zu erkennen. Da bei der Deklaration reiner Funktionen klar definiert werden muss, was sie als Eingabe und Rückgabe erhalten, sind Funktionen, die nichts akzeptieren oder zurückgeben, nicht sauber. Wenn Sie sich entscheiden, funktionale Programmiertechniken in Ihr Projekt aufzunehmen, möchten Sie wahrscheinlich als erstes Ihre Funktionsdeklarationen überprüfen.
Was funktionale Programmierung nicht ist
▍Karten und reduzieren Sie Funktionen
Schleifen sind Mechanismen, die nichts mit funktionaler Programmierung zu tun haben. Schauen Sie sich die folgenden Python-Schleifen an:
integers = [1,2,3,4,5,6]
odd_ints = []
squared_odds = []
total = 0
for i in integers:
if i%2 ==1
odd_ints.append(i)
for i in odd_ints:
squared_odds.append(i*i)
for i in squared_odds:
total += i
Mit Hilfe dieses Codes lösen wir einfache Probleme, die sich jedoch als ziemlich lang herausstellten. Darüber hinaus ist es nicht funktionsfähig, da hier globale Variablen geändert werden.
Und jetzt - eine andere Version dieses Codes:
from functools import reduce
integers = [1,2,3,4,5,6]
odd_ints = filter(lambda n: n % 2 == 1, integers)
squared_odds = map(lambda n: n * n, odd_ints)
total = reduce(lambda acc, n: acc + n, squared_odds)
Dies ist voll funktionsfähiger Code. Es ist kürzer. Es ist schneller, weil Sie nicht über viele Array-Elemente iterieren müssen. Und wenn Sie die Funktionen verstehen
filter, mapund reducees stellt sich heraus , dass dieser Code nicht viel schwieriger ist als das zu verstehen , in denen Schleifen verwendet werden.
Dies bedeutet nicht , dass in jedem Funktionscode wird verwendet
map, reduceund andere solche Funktionen. Dies bedeutet nicht, dass Sie die funktionale Programmierung kennen müssen, um mit solchen Funktionen umgehen zu können. Der Punkt ist, dass diese Funktionen häufig verwendet werden, wenn Schleifen entfernt werden.
▍Lambda-Funktionen
Wenn Menschen über die Geschichte der funktionalen Programmierung sprechen, beginnen sie oft damit, über die Erfindung von Lambda-Funktionen zu sprechen. Während Lambda-Funktionen zweifellos der Eckpfeiler der funktionalen Programmierung sind, sind sie nicht die Hauptursache für FP.
Lambda-Funktionen sind Werkzeuge, mit denen Programme in einem funktionalen Stil geschrieben werden können. Diese Funktionen können aber auch in der objektorientierten Programmierung eingesetzt werden.
▍Statische Eingabe
Das obige Beispiel ist nicht statisch typisiert. Trotzdem handelt es sich um ein Funktionscodebeispiel.
Obwohl die statische Eingabe Ihrem Code eine zusätzliche Sicherheitsebene hinzufügt, ist es nicht erforderlich, Funktionscode zu erstellen. Es kann jedoch eine schöne Ergänzung zum funktionalen Programmierstil sein.
Es ist zu beachten, dass einige Sprachen einfacher in einem funktionalen Stil zu programmieren sind als andere.
Einige Sprachen sind "funktionaler" als andere
▍Perl
Perl hat einen Ansatz zum Umgang mit Nebenwirkungen, der es von den meisten anderen Sprachen unterscheidet. Es hat nämlich eine "magische Variable"
$_, die Nebenwirkungen auf das Niveau eines der Hauptmerkmale der Sprache bringt. Perl hat seine Vorzüge, aber ich würde nicht versuchen, funktionale Programmierung in dieser Sprache durchzuführen.
▍Java
Ich wünsche Ihnen viel Glück beim Schreiben von funktionalem Java-Code. Es wird dir nicht weh tun. Erstens nimmt das Schlüsselwort die Hälfte des Codes ein
static. Zweitens nennen die meisten Java-Programmierer Ihren Code ein Missverständnis.
Dies bedeutet nicht, dass Java eine schlechte Sprache ist. Es ist jedoch nicht dazu gedacht, die Probleme zu lösen, für die die funktionale Programmierung großartig ist. Zum Beispiel - für die Datenbankverwaltung oder für die Entwicklung von Anwendungen aus dem Bereich des maschinellen Lernens.
»Scala
Scala ist eine interessante Sprache. Ziel ist es, funktionale und objektorientierte Programmierung zu vereinheitlichen. Wenn Ihnen das seltsam vorkommt, dann wissen Sie, dass Sie nicht allein sind. Schließlich zielt die funktionale Programmierung darauf ab, Nebenwirkungen vollständig zu beseitigen. Bei der objektorientierten Programmierung geht es darum, Nebenwirkungen auf Objekte zu beschränken.
Vor diesem Hintergrund können wir sagen, dass viele Entwickler Scala als eine Sprache betrachten, die ihnen hilft, von der objektorientierten zur funktionalen Programmierung überzugehen. Die Verwendung von Scala kann ihnen den Übergang zu einem voll funktionsfähigen Programmierstil in der Zukunft erleichtern.
▍Python
Der funktionale Programmierstil wird in Python empfohlen. Dies kann verstanden werden, wenn wir die Tatsache berücksichtigen, dass jede Funktion standardmäßig mindestens einen Parameter hat -
self. Dies ist in vielerlei Hinsicht im Sinne von " Zen Python ": "Explizit ist besser als implizit."
LoClojure
Clojure ist laut dem Schöpfer der Sprache zu etwa 80% funktionsfähig. Alle Werte sind standardmäßig unveränderlich. Genau dies ist jedoch erforderlich, um Funktionscode zu schreiben. Sie können dies jedoch umgehen, indem Sie veränderbare Container verwenden, in die unveränderliche Werte eingefügt werden. Und wenn Sie den Wert aus dem Container extrahieren, wird er wieder unveränderlich.
»Haskell
Es ist eine der wenigen voll funktionsfähigen und statisch typisierten Sprachen. Während die Verwendung im Entwicklungsprozess zu lange dauert, um funktionale Mechanismen zu implementieren, zahlt sich ein solcher Aufwand beim Debuggen von Code um ein Vielfaches aus. Diese Sprache ist nicht so einfach zu lernen wie andere, aber es ist definitiv eine lohnende Investition, sie zu lernen.
Ergebnis
Es sollte beachtet werden, dass jetzt noch der Beginn der Ära von Big Data ist. Big Data kommt und nicht allein, sondern mit einem Freund - mit funktionaler Programmierung.
Funktionale Programmierung ist im Vergleich zur objektorientierten Programmierung immer noch ein Nischenphänomen. Wenn wir jedoch die Integration von FP-Prinzipien in Python und anderen Sprachen als ein bedeutendes Phänomen betrachten, können wir daraus schließen, dass die funktionale Programmierung immer beliebter wird.
Und das ist sinnvoll, denn funktionale Programmierung zeigt sich gut in der Arbeit mit Datenbanken, in der parallelen Programmierung im Bereich des maschinellen Lernens. Und in den letzten zehn Jahren hat all dies zugenommen.
Während objektorientierter Code unzählige Vorteile bietet, sollte Funktionscode nicht übersehen werden. Wenn ein Programmierer einige der Grundprinzipien von FP lernt, kann dies in den meisten Fällen ausreichen, um sein berufliches Niveau zu verbessern. Dieses Wissen wird ihm auch helfen, sich auf eine „funktionale Zukunft“ vorzubereiten.
Wie stehen Sie zur funktionalen Programmierung?
