Strings
let s = "Hallo F#-Welt"
printfn "%d %s %s" s.Length (s.ToUpper()) (s.ToLower())
printfn "%c %s %s" s.[0] (s.Substring(6, 2)) s.[6..7]
printfn "%s" (s.Replace("Welt", "Erde"))
printfn "%A" (s.Split([| ' '; '-' |]))
printfn "%b %b" (s.Contains "F#") (s.StartsWith "Hallo")
printfn "%s" (String.concat ", " [ "a"; "b"; "c" ])
printfn "%s" (String.replicate 3 "ab")
printfn "[%s]" (" trim ".Trim())
printfn "%d" (s.IndexOf "F#")
printfn "%s" (System.String(Array.rev (s.ToCharArray())))
printfn "%A" (s |> Seq.filter System.Char.IsUpper |> Seq.toList)
printfn "%s" (sprintf "%05d|%-6s|%8.3f|%x|%e" 42 "li" 3.14159 255 12345.678)
printfn "%s" ((42).ToString("D5"))
printfn "%s" (System.String.Join("-", [| 1; 2; 3 |]))
let name = "Mia"
let alter = 17
printfn "%s" $"{name} ist {alter} Jahre alt, nächstes Jahr {alter + 1}"
printfn "%s" $"{3.14159:F2} | {255:X} | {1234567:N0}"
printfn "%d" (int "17" + 1)
printfn "%A" (System.Int32.TryParse "abc")
printfn "%A" (System.Int32.TryParse "42")
printfn "%s" (string (char (int 'A' + 1)))
printfn "%s" ("""Dreifache "Anführungszeichen" erlauben Text mit "Zitaten".""")
printfn "%s" (@"C:\Pfad\ohne\Escapes")Ausgabe
13 HALLO F#-WELT hallo f#-welt H F# F# Hallo F#-Erde [|"Hallo"; "F#"; "Welt"|] true true a, b, c ababab [trim] 6 tleW-#F ollaH ['H'; 'F'; 'W'] 00042|li | 3.142|ff|1.234568e+004 00042 1-2-3 Mia ist 17 Jahre alt, nächstes Jahr 18 3.14 | FF | 1,234,567 18 (false, 0) (true, 42) B Dreifache "Anführungszeichen" erlauben Text mit "Zitaten". C:\Pfad\ohne\Escapes
Dateien
open System.IO
let pfad = Path.Combine(Path.GetTempPath(), "fsharp-demo.txt")
File.WriteAllLines(pfad, [ "eins"; "zwei"; "drei" ])
File.AppendAllText(pfad, "vier\n")
let zeilen = File.ReadAllLines pfad
printfn "%d Zeilen: %A" zeilen.Length zeilen
printfn "%d" (File.ReadAllText(pfad).Length)
for zeile in File.ReadLines pfad do
printfn "> %s" zeile
use leser = new StreamReader(pfad)
printfn "%s" (leser.ReadLine())
leser.Close()
printfn "%b %d" (File.Exists pfad) (FileInfo(pfad).Length)
File.Delete pfad
printfn "%b" (File.Exists pfad)
printfn "%s %s" (Path.GetFileName "/tmp/a/b.txt") (Path.GetExtension "b.txt")
let verz = Path.Combine(Path.GetTempPath(), "fsdir")
Directory.CreateDirectory verz |> ignore
File.WriteAllText(Path.Combine(verz, "a.txt"), "A")
File.WriteAllText(Path.Combine(verz, "b.txt"), "B")
printfn "%A" (Directory.GetFiles(verz) |> Array.map Path.GetFileName |> Array.sort)
Directory.Delete(verz, true)Ausgabe
4 Zeilen: [|"eins"; "zwei"; "drei"; "vier"|] 20 > eins > zwei > drei > vier eins true 20 false b.txt .txt [|"a.txt"; "b.txt"|]
Async und Tasks
Asynchrone Abläufe schreibt man in async { } oder task { }:
let berechne n = async {
do! Async.Sleep 10
return n * n
}
let ergebnisse =
[ 1 .. 5 ]
|> List.map berechne
|> Async.Parallel
|> Async.RunSynchronously
printfn "%A" ergebnisse
let aufgabe = task {
do! System.Threading.Tasks.Task.Delay 10
return "fertig"
}
printfn "%s" aufgabe.Result
let ablauf = async {
let! a = berechne 3
let! b = berechne 4
return a + b
}
printfn "%d" (Async.RunSynchronously ablauf)
let mit_fehler = async {
try
failwith "kaputt"
return 0
with e -> return -1
}
printfn "%d" (Async.RunSynchronously mit_fehler)Ausgabe
[|1; 4; 9; 16; 25|] fertig 25 -1
Eigene Computation Expressions
async und seq sind Computation Expressions. Mit einem Builder definiert man eigene:
type MaybeBuilder() =
member _.Bind(x, f) = Option.bind f x
member _.Return(x) = Some x
member _.ReturnFrom(x) = x
let maybe = MaybeBuilder()
let teile a b = if b = 0 then None else Some(a / b)
let rechnung a b c = maybe {
let! x = teile a b
let! y = teile x c
return x + y
}
printfn "%A" (rechnung 100 5 2)
printfn "%A" (rechnung 100 0 2)
let protokoll = ResizeArray<string>()
type LogBuilder() =
member _.Bind(x, f) = protokoll.Add(sprintf "Wert %A" x); f x
member _.Return(x) = x
let log = LogBuilder()
let r = log {
let! a = 5
let! b = a * 2
return a + b
}
printfn "%d %A" r (List.ofSeq protokoll)Ausgabe
Some 30 None 15 ["Wert 5"; "Wert 10"]
Merke
- Strings: .NET-Methoden,
sprintf,$"...", Dreifach-Anführungszeichen,@"..." - Dateien mit
System.IO.File,Path,Directory,usefür Aufräumen async { }undtask { }mitlet!/do!;Async.Parallelfür Parallelität- Computation Expressions mit eigenem Builder (
Bind,Return) bauen eigene „Syntaxen“
Aufgabe
Lade mit Async.Parallel drei Dateien gleichzeitig und summiere ihre Längen.