Funktionsmuster
Sie haben bisher repetitive Ausdrücke in Funktionen umgewandelt. Ihr Code ist nun übersichtlicher und verständlicher. Wenn Sie mit der Verwendung von Funktionen vertraut sind, sollten Sie sich mit effizienteren Programmiermustern befassen. Durch diese Muster erhalten Sie Code, der leichter zu lesen und zu verwalten ist.
Deklarativer und imperativer Ansatz im Vergleich
Wenn Sie mit dem Programmieren beginnen, schreiben Sie zuerst wahrscheinlich einen Ausdruck. Dann schreiben Sie einen weiteren Ausdruck, gefolgt von weiteren Ausdrücken. Sie möchten ein Problem lösen und wissen genau, wie Sie es lösen können. Dieser Ansatz wird als imperativer Ansatz bezeichnet. Daran ist nichts verkehrt, denn so wird das vorliegende Problem gelöst. Es gibt jedoch auch eine andere Möglichkeit, den deklarativen Ansatz. Ein Beispiel für einen deklarativen Ansatz ist das Abfragen einer Datenbank mithilfe von SQL.
Hier sehen Sie einen Beispielausdruck:
SELECT *
FROM Students s
WHERE s.Location = "Ohio"
In diesem Code geben Sie an, was Sie wünschen, aber nicht, wie das Problem gelöst werden soll. Das ist es, was diesen Code deklarativ macht. Das Wie überlassen Sie SQL.
Sie können diesen Ansatz auch auf F# anwenden. Der folgende Code verwendet einen deklarativen Ansatz:
let studentsFromOhio =
allStudents
|> filterLocation "Ohio"
Im vorherigen Code können Sie die vorliegenden Daten nutzen und ein gewünschtes Ziel angeben, ohne genau zu definieren, wie es erreicht werden soll. Wenn Ihr Code wie das vorherige Beispiel aussieht, ist er leicht zu lesen und zu verstehen. Damit Sie an diesen Punkt gelangen, müssen Sie sich mit einigen nützlichen Mustern befassen, die in F# unterstützt werden.
Funktionsmuster
F# enthält einige nützliche Muster, mit denen Sie einen funktionaleren Ansatz verfolgen können. Die folgenden Muster werden behandelt:
- Komposition: Eine Komposition kombiniert mehrere Funktionen zu einer Funktion.
- Pipeline: Eine Pipeline beginnt mit einem Wert und ruft dann nacheinander mehrere Funktionen auf, indem sie die Ausgabe einer Funktion als Eingabe für die nächste Funktion verwendet.
Zusammensetzung
Bei der Komposition werden Funktionen und deren Anwendung in einer bestimmten Reihenfolge nacheinander kombiniert. Der Kompositionsoperator nimmt zwei Funktionen an und gibt eine neue Funktion zurück.
Beim Erstellen von Code rufen Sie häufig eine Funktion und dann direkt danach eine weitere Funktion auf. Das gilt beispielsweise, wenn Sie eine Liste sortieren und alle Produkte herausfiltern möchten, die im Sonderangebot sind.
Im folgenden Beispiel wird die Funktion add2() aufgerufen, und das Ergebnis wird an die Funktion multiply3() übergeben.
let add2 a = a + 2
let multiply3 a = a * 3
let addAndMultiply a =
let sum = add2 a
let product = multiply3 sum
product
printfn "%i" (addAndMultiply 2) // 12
Dieses Muster kommt so häufig vor, dass F# über einen Operator dafür verfügt. Mit dem Operator >> können Sie zwei oder mehr Funktionen zu einer größeren Funktion kombinieren. Durch die Verwendung des Operators >> können Sie den vorangehenden Code folgendermaßen vereinfachen:
let add2 a = a + 2
let multiply3 a = a * 3
let addAndMultiply = add2 >> multiply3
printfn "%i" (addAndMultiply 2) // 12
Die kombinierte Funktion addAndMultiply() wendet die Funktionen an, aus der sie besteht, und zwar von links nach rechts. In diesem Beispiel wird add2() zuerst und multiply3() zuletzt verarbeitet.
Rohrleitung
Der Pipelineoperator |> nimmt eine Funktion und ein Argument an und gibt einen Wert zurück. Sehen wir uns anhand dieses Beispiels an, wie sich die Pipeline von einer Komposition unterscheidet:
let list = [4; 3; 1]
let sort (list: int list) = List.sort list
let print (list: int list)= List.iter(fun x-> printfn "item %i" x) list
list |> sort |> print // item 1 item 3 item 4
In der letzten Codezeile beginnen Sie mit einer Liste aus Integern, wobei Sie list verwenden, was als Eingabe für die erste Funktion, sort(), dient. Das Ergebnis dieses Vorgangs wird an print() übergeben. Der große Unterschied zwischen Pipelines und Kompositionen besteht darin, dass Sie mit einigen Daten beginnen, in diesem Fall mit einer Liste aus Integern, und diese dann durch eine Reihe von Funktionen führen.