Funktionsmønstre
Indtil videre har du taget gentagelsesudtryk og placeret disse udtryk i funktioner. Din kode ser nu bedre ud og er nemmere at læse. Efterhånden som du vænner dig til at bruge funktioner, er det værd at begynde at se på nogle effektive mønstre, der findes på dette område. Når du bruger disse mønstre, får du kode, der er nemmere at læse og vedligeholde.
Deklarativ vs. essentiel
Når du begynder at kode, skriver du sandsynligvis et udtryk. Derefter skriver du et andet udtryk efterfulgt af et andet, et efter et. Dit fokus er på at løse problemet, og du er specifik om, hvordan du løser det. Denne fremgangsmåde kaldes en essentiel tilgang. Der er ikke noget galt med det, fordi det løser problemet ved hånden. Men der er en anden vej at gå, som er den deklarative tilgang. Du kan se et eksempel på en deklarativ tilgang, når du forespørger en database ved hjælp af SQL.
Her er et eksempel på et udtryk:
SELECT *
FROM Students s
WHERE s.Location = "Ohio"
Det, der gør denne kodedeklarativ, er, at du beder om , hvad du vil have, men du angiver ikke , hvordan du vil have problemet løst. Du overlader , hvordan til SQL.
Du kan også anvende denne fremgangsmåde på F#. Følgende kode bruger en deklarativ tilgang:
let studentsFromOhio =
allStudents
|> filterLocation "Ohio"
I den foregående kode arbejder du med data og beder om det, du vil, uden at være specifik for, hvordan du vil have det gjort. Når din kode ligner det foregående eksempel, er det nemt at læse og overveje. Lad os se på nogle nyttige mønstre, der understøttes i F#, for at komme til dette punkt.
Funktionelle mønstre
Der er nogle nyttige mønstre i F#, som du kan bruge til at tage en mere funktionel tilgang. Vi dækker følgende mønstre:
- Composition: En komposition kombinerer flere funktioner til én funktion.
- Pipeline: En pipeline starter med en værdi og kalder derefter sekventielt flere funktioner ved hjælp af outputtet fra én funktion som input for den næste funktion.
Sammensætning
Komposition handler om at kombinere funktioner og anvende dem, den ene efter den anden, i en bestemt rækkefølge. Kompositionsoperatoren tager to funktioner og returnerer en ny funktion.
Når du opretter kode, vil du ofte kalde én funktion og derefter en anden funktion lige efter den. Det kan f.eks. være, at du vil bestille en liste og filtrere alle produkter, der har rabat, fra.
I følgende eksempel kaldes funktionen add2(), og dens resultat overføres til funktionen multiply3().
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
Dette mønster er så almindeligt, at F# har en operator til det. Med operatoren >> kan du kombinere to eller flere funktioner til én større funktion. Ved hjælp af operatoren >> kan du forenkle den foregående kode på følgende måde:
let add2 a = a + 2
let multiply3 a = a * 3
let addAndMultiply = add2 >> multiply3
printfn "%i" (addAndMultiply 2) // 12
Den kombinerede funktion addAndMultiply() anvender de funktioner, den består af fra venstre mod højre. I dette eksempel sker add2() først, og multiply3() sker sidst.
Pipeline
Pipelineoperatoren |> tager en funktion og et argument og returnerer en værdi. Lad os se, hvordan pipelinen adskiller sig fra sammensætningen i dette eksempel:
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
I den sidste kodelinje starter du med en liste over heltal, list, der fungerer som input til den første funktion, sort(). Resultatet af denne handling overføres til print(). Den primære forskel mellem pipeline og sammensætning er, at med en pipeline starter du med nogle data, som er en liste over heltal i dette tilfælde, og derefter fører du den gennem et sæt funktioner.