Funktionales Denken. Teil 2

Freunde, wir verstehen weiterhin funktionale Programmierung. Im zweiten Teil dieser Artikelserie lernen Sie die Grundprinzipien dieses Entwicklungsparadigmas kennen und verstehen, wie sich dieser Ansatz von der objektorientierten oder imperativen Programmierung unterscheidet.




Werte und Funktionen


Betrachten Sie noch einmal diese einfache Funktion.


let add1 x = x + 1 

Was bedeutet x hier:


  1. Nehmen Sie einen Wert aus der Domäne (Bereich).
  2. Verwenden Sie den Namen " x ", um diesen Wert anzugeben, damit später darauf zugegriffen werden kann.

Die Verwendung eines Namens zur Darstellung eines Werts wird als Bindung bezeichnet. Der Name " x " ist an den Eingabewert "gebunden".


Wenn Sie also eine Funktion mit einem Eingabewert von beispielsweise 5 berechnen, geschieht Folgendes: Wo immer „ x “ in der ursprünglichen Definition enthalten ist, wird der Wert 5 festgelegt, ähnlich wie bei der Funktion „Suchen und Ersetzen“ in einem Texteditor.


 let add1 x = x + 1 add1 5 //  «x» with «5» // add1 5 = 5 + 1 = 6 //  6 

Es ist wichtig zu verstehen, dass dies keine Aufgabe ist. " x " ist kein "Slot" und keine Variable mit einem zugewiesenen Wert, der später geändert werden kann. Dies ist eine einmalige Zuordnung des Namens " x " zu einem bestimmten Wert. Dieser Wert ist eine der vordefinierten Ganzzahlen und kann nicht geändert werden. Das heißt, einmal gebundenes x kann nicht mehr geändert werden . Die dem Wert einmal zugeordnete Bezeichnung ist für immer diesem Wert zugeordnet.


Dieses Prinzip ist ein kritischer Bestandteil des funktionalen Denkens: Es gibt keine "Variablen", nur Werte .


Funktioniert als Werte


Wenn Sie etwas länger darüber nachdenken, können Sie sehen, dass der Name " add1 " an sich nur eine Bindung an "eine Funktion, die die Eingabe um eins erhöht" ist. Die Funktion selbst ist unabhängig von dem Namen, der ihr zugeordnet ist.


Durch die Einführung von let add1 x = x + 1 sagen wir dem F # -Compiler: "Jedes Mal, wenn Sie den Namen" add1 "sehen, ersetzen Sie ihn durch eine Funktion, die der Eingabe 1 hinzufügt." " add1 " wird als Funktionswert bezeichnet .


Um zu sehen, dass die Funktion nicht von ihrem Namen abhängt, reicht es aus, den folgenden Code auszuführen:


 let add1 x = x + 1 let plus1 = add1 add1 5 plus1 5 

Wie Sie sehen können, sind " add " und " plus " zwei Namen, die an dieselbe Funktion gebunden sind.


Sie können eine Wertfunktion immer anhand ihrer Signatur identifizieren, die die Standardformulardomäne domain -> range . Die verallgemeinerte Signatur der Wertfunktion:


 val functionName : domain -> range 

Einfache Werte


Stellen Sie sich eine Operation vor, die nichts benötigt und immer 5 zurückgibt.



Es wäre eine "konstante" Operation.


Wie könnte dies in F # beschrieben werden? Wir möchten dem Compiler sagen: "Jedes Mal, wenn Sie den Namen c , ersetzen Sie ihn durch 5". So:


 let c = 5 

Bei der Berechnung wird zurückgegeben:


 val c : int = 5 

Diesmal gibt es keinen passenden Pfeil, nur einen int. Aus dem Neuen - ein Gleichheitszeichen mit dem danach abgeleiteten realen Wert. Der F # -Compiler weiß, dass diese Bindung einen bekannten Wert hat, der immer zurückgegeben wird, nämlich die Nummer 5.


Mit anderen Worten, wir haben nur eine Konstante oder in Form von F # einen einfachen Wert definiert.
Sie können einen einfachen Wert immer von einer Wertefunktion unterscheiden, da alle einfachen Werte eine ähnliche Signatur haben:


 val aName: type = constant //  -   

Einfache Werte vs. Funktionswerte | Einfache Bedeutung vs. Wertfunktionen


Es ist wichtig zu verstehen, dass in F # im Gegensatz zu anderen Sprachen wie C # nur ein sehr geringer Unterschied zwischen einfachen Werten und Wertefunktionen besteht. Beide Typen sind Werte, die Namen zugeordnet werden können (mithilfe des Schlüsselworts let ). Danach können sie überall übergeben werden. Tatsächlich werden wir bald sehen, dass die Idee, dass Funktionen Werte sind, die als Eingabe an andere Funktionen übergeben werden können, einer der Schlüsselaspekte des funktionalen Denkens ist.


Beachten Sie, dass zwischen einem einfachen Wert und einer Wertefunktion ein geringfügiger Unterschied besteht. Eine Funktion hat immer Domäne und Bereich und muss auf das Argument "angewendet" werden, um das Ergebnis zurückzugeben. Ein einfacher Wert muss nach dem Binden nicht berechnet werden. Wenn wir im obigen Beispiel eine „konstante Funktion“ definieren möchten, die 5 zurückgibt, können wir Folgendes verwenden:


 let c = fun()->5 // or let c() = 5 

Die Signatur solcher Funktionen sieht folgendermaßen aus:


 val c : unit -> int 

Nicht so:


 val c : int = 5 

Weitere Informationen zu unit , Funktionssyntax und anonymen Funktionen erhalten Sie später.


"Werte" vs. "Objekte"


In funktionalen Programmiersprachen wie F # werden die meisten Dinge als "Werte" bezeichnet. In objektorientierten Sprachen wie C # werden die meisten Dinge als "Objekte" bezeichnet. Was ist der Unterschied zwischen "Bedeutung" und "Objekt"?


Der Wert ist, wie wir oben gesehen haben, ein Mitglied der Domain. Die Domäne von Ganzzahlen, die Domäne von Zeichenfolgen, die Domäne von Funktionen, die Ganzzahlen Zeichenfolgen zuordnen, und so weiter. Grundsätzlich sind die Werte unveränderlich (nicht veränderlich). Und den Bedeutungen ist nicht das Verhalten zugeordnet.


Objekte in der kanonischen Definition sind die Kapselung der Datenstruktur mit zugehörigem Verhalten (Methoden). Im Allgemeinen müssen Objekte einen Status haben (dh veränderbar sein), und alle Operationen, die den internen Status ändern, müssen vom Objekt selbst bereitgestellt werden (über eine "Punkt" -Notation).


In F # haben sogar primitive Werte ein bestimmtes Objektverhalten. Sie können beispielsweise die Länge eines Strings durch einen Punkt ermitteln:


 «abc».Length 

Im Allgemeinen vermeiden wir jedoch den Begriff „Objekt“ für Standardwerte in F # und speichern ihn, um auf vollwertige Klassen oder andere Werte zu verweisen, die Methoden bereitstellen.


Werte benennen


Die Standard-Namenskonventionen für Wert- und Funktionsnamen sind grundsätzlich alphanumerische + Unterstriche. Es gibt jedoch einige Ergänzungen:


  1. Sie können in jedem Teil des Namens ein Apostroph hinzufügen, mit Ausnahme des ersten Zeichens.

 A'b'c begin' //   

  1. Der letztere Fall wird häufig als Bezeichnung für "verschiedene" Versionen eines Werts verwendet:

 let f = x let f' = derivative f let f'' = derivative f' 

oder für gleichnamige Variablen mit vorhandenen Schlüsselwörtern


 let if' btf = if b then t else f 

Sie können auch doppelte Backticks für jede Zeichenfolge verwenden, um sie zu einem gültigen Bezeichner zu machen.


 ``this is a name`` ``123`` //  

Fälle, in denen Sie möglicherweise einen Double-Backtick-Trick verwenden müssen:


  • Wenn Sie einen Bezeichner verwenden müssen, der dem Schlüsselwort entspricht.

 let ``begin`` = «begin» 

  • Wenn Sie natürliche Sprachen für Geschäftsregeln, Komponententests oder ausführbare Dokumentationen im BBD-Stil wie Cucumber verwenden müssen.

 let ``is first time customer?`` = true let ``add gift to order`` = () if ``is first time customer?`` then ``add gift to order`` // - let [<Test>] ``When input is 2 then expect square is 4``= // code here // BDD clause let [<Given>] ``I have (.*) N products in my cart`` (n:int) = // code here 

Im Gegensatz zu C # erfordert die F # camelCase , dass Funktionen und Werte mit einem Kleinbuchstaben und nicht mit Großbuchstaben ( camelCase , nicht PascalCase ) beginnen, es sei denn, sie sind für die Interaktion mit anderen .NET-Sprachen ausgelegt. Typen und Module verwenden jedoch (am Anfang) Großbuchstaben.


Zusätzliche Ressourcen


Es gibt viele Tutorials für F #, einschließlich Materialien für diejenigen, die mit C # oder Java-Erfahrung kommen. Die folgenden Links können hilfreich sein, wenn Sie tiefer in F # einsteigen:



Es werden auch verschiedene andere Möglichkeiten beschrieben , um mit dem Lernen von F # zu beginnen .


Schließlich ist die F # Community sehr anfängerfreundlich. Bei Slack gibt es einen sehr aktiven Chat, der von der F # Software Foundation unterstützt wird, mit Anfängerräumen, an denen Sie frei teilnehmen können . Wir empfehlen Ihnen dringend, dies zu tun!


Vergessen Sie nicht, die Seite der russischsprachigen Community F # zu besuchen! Wenn Sie Fragen zum Erlernen einer Sprache haben, diskutieren wir diese gerne in Chatrooms:



Über Übersetzungsautoren


Übersetzt von @kleidemos
Übersetzungs- und redaktionelle Änderungen wurden durch die Bemühungen der russischsprachigen Community von F # -Entwicklern vorgenommen . Wir danken auch @schvepsss und @shwars für die Vorbereitung dieses Artikels zur Veröffentlichung.

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


All Articles