Funktionale Programmierung sollte 2015 Ihre oberste Priorität sein

"Die PLO kann uns nicht länger vor den Wolkenmonstern retten."



Anmerkung des Übersetzers: Es gibt zwei Konzepte - Parallelität (gleichzeitige, unabhängige Ausführung) und Wettbewerbsfähigkeit (schrittweise Ausführung, aber gleichzeitig mehrere Aufgaben), und wie immer musste ich mir den Kopf zerschlagen, indem ich die richtigen Begriffe auswählte.

Ich werde einige Wörter oder Begriffe in Klammern im Original duplizieren, um nach zusätzlichen Informationen in englischen Begriffen zu suchen, die um ein Vielfaches höher sein werden.


Vielleicht haben Sie schon einen solchen Ausdruck gehört, wie: "Clojure", "Scala", "Erlang" oder sogar "Java hat jetzt Lambdas". Und Sie haben, wenn auch eine entfernte Vorstellung von "funktionaler Programmierung". Wenn Sie Mitglied einer Programmiergemeinschaft sind, könnte dieses Thema bereits von Ihnen diskutiert werden.

Wenn Sie Google nach dem Begriff "Funktionale Programmierung" durchsuchen, wird nichts Neues angezeigt. Die zweite Sprache der zuvor erstellten Sprache behandelt dieses Thema bereits: Sie wurde in den 50er Jahren erstellt und heißt Lisp. Was zum Teufel ist dieses Thema gerade jetzt populär geworden? Nur 60 Jahre später?

Am Anfang waren Computer sehr langsam



Ob Sie es glauben oder nicht, Computer waren am langsameren als das DOM. Nicht wirklich. Gleichzeitig enthielt die Vereinbarung zwei Hauptideen zum Entwurf und zur Implementierung von Programmiersprachen:

  • Beginnen Sie mit der von Neumann-Architektur und fügen Sie Abstraktion hinzu.
  • Beginnen Sie mit Mathe und entfernen Sie die Abstraktion.



Computer hatten nicht genügend Rechenleistung, um alle Abstraktionen zu verarbeiten und Programme zu verarbeiten, die in einem funktionalen Stil geschrieben wurden. So war Lisp vorher erschöpft, extrem langsam und daher nicht für die Arbeit geeignet. Zu diesem Zeitpunkt begann die Dominanz des imperativen Programmierstils, insbesondere mit der Blütezeit von C.

Aber Computer haben sich sehr verbessert.



Jetzt ist es fast normal geworden, die meisten Anwendungen zu verwenden, ohne sich darum zu kümmern, in welcher Sprache sie geschrieben wurden. Funktionale Sprachen haben endlich eine zweite Chance bekommen.

Funktionsprogrammierung 50.5



Dieser Artikel ist keineswegs eine Einführung in FI. Am Ende dieses Abschnitts müssen Sie wissen, was AF ist und wie Sie Ihre Studienreise beginnen können.

Sie können den Begriff „funktionale Programmierung“ zu wörtlich als Programmieren mit Funktionen verstehen, und dies ist nicht weit von der Wahrheit entfernt. Sie werden Funktionen in Bezug auf andere Funktionen erstellen und Funktionen schreiben (Erinnern Sie sich an f ∘ g aus dem Lehrplan? Jetzt wird es nützlich sein). Das ist alles.

Die Liste (nicht vollständig) der Funktionen von FP:

  1. Erstklassige Funktionen
  2. Funktionen höherer Ordnung
  3. Reine Funktionen
  4. Verschlüsse
  5. Unveränderlicher Staat


Jetzt müssen Sie sich keine Gedanken mehr über diese seltsamen Begriffe machen, sondern nur verstehen, was sie bedeuten.

Funktionen der ersten Klasse bedeuten, dass Sie Funktionen in Variablen speichern können. Ich bin sicher, Sie haben etwas Ähnliches getan, wie im JavaScript-Beispiel:

var add = function(a, b){
  return a + b
}

Sie haben gerade eine anonyme Funktion erstellt, die a und b erhält und a + b zurückgibt und diese Funktion der Variablen add zuweist .

Funktionen höherer Ordnung bedeuten, dass Funktionen Funktionen zurückgeben oder Funktionen als Parameter akzeptieren können.

Und wieder in JavaScript:

document.querySelector('#button')
  .addEventListener('click', function(){
    alert('yay, i got clicked')
  })

oder

var add = function(a){
  return function(b){
    return a + b
  }
}
 
var add2 = add(2)
add2(3) // => 5


Beide Optionen sind ein Beispiel für Funktionen höherer Ordnung. Auch wenn Sie so etwas nicht geschrieben haben, haben Sie möglicherweise woanders etwas Ähnliches gesehen.

Reine Funktionen bedeuten, dass die Funktion die Variablen nicht ändert, sondern einfach die Daten akzeptiert und die Daten zurückgibt, wie unsere Lieblingsfunktionen aus der Mathematik. Dies bedeutet auch, dass, wenn Sie die Funktion f mit Argument 2 aufrufen und 10 zurückgeben , immer 10 zurückgegeben wird . Es spielt keine Rolle, welche Umgebung, Anzahl der Threads oder Ausführungsreihenfolge. Sie verursachen keine Nebenwirkungen in anderen Teilen des Programms und dies ist ein wirklich mächtiges Konzept.

Kurzschlüsse bedeutet, dass Sie einige Daten in der Funktion speichern können, die in einer bestimmten Rückgabefunktion verfügbar sind. Mit anderen Worten, die Rückgabefunktion speichert ihre Laufzeit.

var add = function(a){
  return function(b){
    return a + b
  }
}
 
var add2 = add(2)
add2(3) // => 5

Schauen Sie sich noch einmal das zweite Beispiel aus dem Absatz Funktionen höherer Ordnung an . Die Variable a wurde geschlossen und ist nur in der zurückgegebenen Funktion verfügbar. In der Tat sind Verschlüsse kein Merkmal des FP-Paradigmas, sondern vielmehr eine Optimierung.

Ein unveränderlicher Status bedeutet, dass Sie keinen Status ändern können (obwohl Sie neue erstellen können). Im folgenden Code (unter OCaml) setzen Sie die Variable x auf 5 und x ist immer 5 .

let x = 5;;
x = 6;;

print_int x;;  (* prints 5 *)


Diese Funktionen sehen seltsam genug aus, aber Sie werden bald sehen, wie sie Ihnen das Leben erleichtern.

Objektorientierte Programmierung kann Sie nicht mehr schützen



Dies ist eine vielversprechende Zeit, in der wir endlich verteilte und Multithread-Anwendungen haben können. Leider ist unser vorhandenes (oder am häufigsten verwendetes) Modell nicht für Parallelität und Parallelität bereit, obwohl es aktuelle Probleme löst, aber auch große Probleme hinzufügt.

Um Anwendungen zu verbessern, benötigen wir einen einfachen und zuverlässigen Weg, um das zu erreichen, was wir wollen. Erinnern Sie sich an die oben genannten Funktionen von AF? Reine Funktionen und unveränderlicher Zustand? Richtig, Sie können Funktionen tausende Male auf verschiedenen Kernen oder Maschinen ausführen, und das Ergebnis ist immer das gleiche. Auf diese Weise können wir denselben Code auf demselben Kern und auf Tausenden ausführen. Das Leben wird wieder wolkenlos.

"Aber warum kann ich OOP nicht weiter verwenden?"



Zumindest für Multithreading und Parallelität kann OOP Ihnen nicht mehr weiterhelfen. Weil sich OOP auf einen Zustand mit einem veränderlichen Zustand bezieht (in imperativen Sprachen, die in den meisten Fällen im OOP-Stil geschrieben sind). Die aufgerufenen Methoden des Objekts sollen das aktuelle Selbst oder dies ändern . Sie müssen sich genügend Mühe geben, um alle Threads korrekt zu aktualisieren und zu synchronisieren.

Ich schreibe dies, um Sie nicht dazu zu bewegen, von den Paradigmen, die Sie derzeit verwenden, zu FP zu wechseln (obwohl einige Leute sagen, ich sollte es tun), aber Sie sollten auf jeden Fall verstehen: Java und C ++ 11 haben bereits Lambda-Kalkül. Ich kann sagen, dass fast alle modernen und unterstützten Sprachen FP-Funktionen implementieren werden oder dies bereits getan haben.

Es ist erwähnenswert, dass wir nicht aufhören sollten, den veränderlichen Zustand zu verwenden. Wir müssen Input / Output (IO) usw. verwenden, damit unsere Programme nützlich sind. Die Hauptidee von FP ist: Verwenden Sie einen veränderlichen Zustand nur dann, wenn er wirklich benötigt wird.

"Ich arbeite nicht mit Wolken. Muss ich wirklich AF lernen?"



Ja.

Die funktionale Programmierung hilft Ihnen dabei, Programme besser zu schreiben und über Probleme zu sprechen, die Sie lösen müssen.

"Ich habe versucht. Es ist zu kompliziert und schwer, Code zu lesen. “



Das Starten ist in jedem Bereich immer schwierig. Ich bin sicher, Sie haben angefangen, Programmieren zu lernen, und es gab auch eine Reihe von Problemen, selbst in OOP-Sprachen. Vielleicht war es einfacher, mit dem Schreiben im OOP-Stil zu beginnen, als mit dem Schreiben Ihres ersten Programms, da Sie bereits mit einigen gängigen Redewendungen wie dem Deklarieren von Variablen und for / while-Schleifen vertraut waren.

Das Erlernen von FP ist fast das Gleiche wie das erneute Schreiben von Programmen von Grund auf neu (unabhängig davon, welche Sprache Sie zu lernen begonnen haben, ist es eindeutig, wie Sie von vorne beginnen sollen).

Viele mögen bemerken, dass AF schwer zu lesen ist. Wenn Sie Erfahrung in imperativen Sprachen haben, sehen funktionale Programme wie Kryptographie aus. Und nicht, weil es wirklich so ist, sondern weil Sie die wichtigsten Redewendungen nicht kennen. Sobald die Grundprinzipien verstanden sind, werden die Programme viel lesbarer.

Schauen Sie sich das in Haskell und JavaScript geschriebene Programm an (zwingend erforderlich):

guess :: Int -> [Char]
guess 7 = "Much 7 very wow."
guess x = "Ooops, try again."

-- strongly inspired by http://learnyouahaskell.com

function guess(x){
  if(x == 7){
    return "Much 7 very wow."
  }
  else {
    return "Oops, try again."
  }
}

Dies ist ein sehr einfaches Programm. Es zeigt eine Glückwunschmeldung an, wenn der Benutzer die Nummer 7 erraten und eingegeben hat, oder zeigt in allen anderen Fällen eine Fehlermeldung an. Vielleicht sieht das nach Verschlüsselung aus, da Haskell die ganze Arbeit in nur zwei Codezeilen erledigen kann (Sie können die erste Zeile ignorieren, es ist nur eine "Typdeklaration"). Aber es wird einmal ganz einfach, wenn man die Möglichkeiten des Mustervergleichs verstanden hat (die nicht nur in FP-Sprachen implementiert sind, sondern deren Merkmal waren).

Was Haskell tut:

Wenn das akzeptierte Argument 7 ist, wird es "Viel 7 sehr wow" zurückgeben. oder wird "Uooops, versuchen Sie es erneut." in anderen Fällen.

Dies ist das Gleiche wie JavaScript-Code, aber Haskell ordnet das vom Programmierer im Code deklarierte "Muster" zu.

Dieser Ansatz scheint in diesem Fall nicht sehr nützlich zu sein, wenn Sie if / else verwenden können. Aber es wird wirklich nützlich, wenn Sie selbst anfangen, komplexere Datenstrukturen zu schreiben.

plus1 :: [Int] -> [Int]
plus1 []      = []
plus1 (x:xs)  = x + 1 : plus1 xs 

-- plus1 [0,1,2,3]
-- > [1,2,3,4]

Im obigen Programm ist * plus1 * eine Funktion, die eine Liste von Ganzzahlen verwendet und jedem Element der Liste 1 hinzufügt. Die Funktion vergleicht, wenn die Liste leer ist [] (gibt eine weitere leere Liste zurück, da keine Elemente darin enthalten sind), umgeht die nicht leere Liste und bestimmt das Übereinstimmungsmuster: x als erstes Element der Liste, xs als verbleibende Liste. Dann berechnet es einfach die Summe und kombiniert sie durch einen rekursiven Aufruf.

Ich bin sicher, Sie werden viele Minuten (nicht die angenehmste) damit verbringen, dieses Beispiel in einem zwingenden Stil neu zu schreiben, den Code in zwei Zeilen anzupassen und gleichzeitig die Lesbarkeit zu gewährleisten.

Also lasst uns anfangen



Es wurde viel Material zur funktionalen Programmierung veröffentlicht, aber Sie sollten diese Links nicht eindeutig überspringen:

  1. Prinzipien der funktionalen Programmierung in Scala : Der Kurs ist nützlich für diejenigen, die Java kennen und die funktionale Programmierung ausprobieren möchten, ohne von der JVM zu springen. Der Kurs behandelt grundlegende Konzepte.
  2. Paradigmen der Computerprogrammierung - Grundlagen : Dieser Kurs ist nützlich für diejenigen, die lernen möchten, wie man Programme in einer funktionalen Sprache schreibt. Der Kurs verwendet die Qz-Lernsprache. Der Kurs enthält viele Übungen. Sie können eine funktionale Sprache verwenden und versuchen, Ihre eigene Datenstruktur zu erstellen. Ich glaube, der Kurs bietet Bausteine ​​für das „Gebäude“ namens „Funktionale Programmierung“. Er wird Ihnen in Zukunft bei anderen Sprachen helfen.


Kurse werden leider erst Ende des Jahres angeboten. Sie können jedoch den Inhalten und Videos folgen, die auf Youtube verfügbar sind.

Wenn Sie jedoch Textmaterialien bevorzugen, empfehle ich einige davon:

  1. Struktur und Interpretation von Computerprogrammen
  2. So entwerfen Sie Programme
  3. Konzepte, Techniken und Modelle der Computerprogrammierung


Die ersten beiden haben ähnliche Lehrpläne, führen Sie in die Grundlagen der funktionalen Programmierung ein und eignen sich sehr gut für Anfänger. Der dritte Link, dieser Kurs in Computerprogrammierparadigmen, behandelt mehr als die funktionale Programmierung. Es ist wichtig zu beachten, dass diese Materialien für den Einstieg gedacht sind.

Darüber hinaus schrieb Chris Allen einen ausgezeichneten Artikel über das Studium der funktionalen Programmierung. Es heißt Functional Education.und verfügt über eine umfassende Liste von Materialien zum Studium der funktionalen Programmierung mit Haskell sowie über die Stärken und Schwächen dieses Ansatzes. Wenn Sie den von Chris empfohlenen Links folgen, können Sie die Grundprinzipien und komplexeren Themen (ich bin sicher, Sie haben von Monaden gehört) der funktionalen Programmierung lernen und vielleicht werden Sie verstehen, wie man Anwendungen mit ihnen schreibt. (Danke Chris für die Links zu den Materialien.)

Viel Glück mit Ihrem funktionalen neuen Jahr!

Source: https://habr.com/ru/post/de383551/


All Articles