EMZETT.
Login

Kurz: printfn “%A” (sieb 50) printfn “%d” (List.length (sieb 10000))

Teil des Kurses F#

Kapitel 7 von 8 im Kurs F#. Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Kleine Projekte

// Primzahlsieb
let sieb n =
    let prim = Array.create (n + 1) true
    for i in 2 .. int (sqrt (float n)) do
        if prim.[i] then
            for j in i * i .. i .. n do prim.[j] <- false
    [ for i in 2 .. n do if prim.[i] then yield i ]
 
printfn "%A" (sieb 50)
printfn "%d" (List.length (sieb 10000))
 
// Caesar
let verschiebe (text: string) schluessel =
    text
    |> String.map (fun c ->
        if System.Char.IsLower c then char ((int c - int 'a' + schluessel + 26) % 26 + int 'a')
        elif System.Char.IsUpper c then char ((int c - int 'A' + schluessel + 26) % 26 + int 'A')
        else c)
 
let geheim = verschiebe "Hallo F#!" 3
printfn "%s" geheim
printfn "%s" (verschiebe geheim -3)

Ausgabe:

[2; 3; 5; 7; 11; 13; 17; 19; 23; 29; 31; 37; 41; 43; 47]
1229
Kdoor I#!
Hallo F#!

Datenanalyse mit Pipelines

type Verkauf = { Region: string; Produkt: string; Menge: int; Preis: decimal }
 
let daten =
    [ { Region = "Nord"; Produkt = "Apfel"; Menge = 10; Preis = 1.20m }
      { Region = "Sued"; Produkt = "Birne"; Menge = 5; Preis = 0.80m }
      { Region = "Nord"; Produkt = "Birne"; Menge = 8; Preis = 0.80m }
      { Region = "West"; Produkt = "Apfel"; Menge = 20; Preis = 1.10m }
      { Region = "Sued"; Produkt = "Apfel"; Menge = 7; Preis = 1.20m } ]
 
let umsatz v = decimal v.Menge * v.Preis
 
daten
|> List.groupBy (fun v -> v.Region)
|> List.sortBy fst
|> List.iter (fun (region, vs) ->
    printfn "%-5s %7.2f" region (vs |> List.sumBy umsatz))
 
printfn "Gesamt: %M" (daten |> List.sumBy umsatz)
let bester = daten |> List.maxBy umsatz
printfn "Bester Posten: %s in %s" bester.Produkt bester.Region
printfn "Äpfel: %d" (daten |> List.filter (fun v -> v.Produkt = "Apfel") |> List.sumBy (fun v -> v.Menge))

Ausgabe:

Nord    18.40
Sued    12.40
West    22.00
Gesamt: 52.80
Bester Posten: Apfel in West
Äpfel: 37

Tests und Ausnahmen

exception MeinFehler of string
 
let pruefe n =
    if n < 0 then raise (MeinFehler(sprintf "negativ: %d" n))
    n
 
try
    printfn "%d" (pruefe 3)
    printfn "%d" (pruefe -1)
with
| MeinFehler msg -> printfn "Eigener Fehler: %s" msg
| ex -> printfn "anderer Fehler: %s" ex.Message
 
let ergebnis =
    try Ok(int "abc")
    with :? System.FormatException as e -> Error e.Message
printfn "%A" ergebnis
 
try
    try failwith "innen"
    finally printfn "finally läuft immer"
with e -> printfn "außen gefangen: %s" e.Message
 
let mutable bestanden = 0
let mutable fehler = 0
let pruefeGleich name erwartet erhalten =
    if erwartet = erhalten then
        bestanden <- bestanden + 1
        printfn "ok     %s" name
    else
        fehler <- fehler + 1
        printfn "FEHLER %s" name
pruefeGleich "Addition" 3 (1 + 2)
pruefeGleich "Liste" [ 2; 4 ] (List.map ((*) 2) [ 1; 2 ])
pruefeGleich "absichtlich" 5 (2 * 2)
printfn "%d bestanden, %d fehlgeschlagen" bestanden fehler

Ausgabe:

3
Eigener Fehler: negativ: -1
Error "The input string 'abc' was not in a correct format."
finally läuft immer
außen gefangen: innen
ok     Addition
ok     Liste
FEHLER absichtlich
2 bestanden, 1 fehlgeschlagen

Ökosystem

WerkzeugZweck
dotnet CLI, NuGetBuild und Pakete
F# Interactive (dotnet fsi)REPL und Skripte (.fsx)
Ionide (VS Code), RiderEditoren
FSharp.DataJSON/CSV/HTML-Typprovider
Giraffe, Saturn, FalcoWeb-Frameworks
FableF# nach JavaScript
Expecto, xUnit, FsCheckTests (inkl. Property-based)
Paket, FAKEPaketmanager und Build-DSL
Polyglot NotebooksDatenanalyse in Notebooks

Merke

  • F# eignet sich hervorragend für Datenverarbeitung, Domänenmodelle und Parser
  • Pipelines (|>) und Records/Unions machen Code kurz und lesbar
  • Ausnahmen mit try ... with, exception und failwith
  • Das .NET-Ökosystem steht vollständig zur Verfügung

Übungsaufgabe

Baue einen kleinen Taschenrechner-Parser mit Discriminated Unions.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Strings, Dateien, Async und Computation Expressions

Weiter: Referenz und Spickzettel

Alle Kapitel: F# im Überblick