Mit einem if/elif/else-Ausdruck kannst du Logik bedingt ausführen. F# hat aber noch eine andere, mächtigere Möglichkeit, Logik bedingt auszuführen: den Musterabgleich. Beim Musterabgleich wird ein Wert gegen ein oder mehrere Muster geprüft. Ein Beispiel für ein solches Muster ist das Konstantenmuster, das einen Wert gegen eine Konstante abgleicht (z. B. 1 oder "hello").
In F# verwendest du für den Musterabgleich das match-Schlüsselwort:
let describe number =
match number with
| 0 -> "Zero"
| 1 -> "One"
Auch wenn das wie switch-Anweisungen in anderen Sprachen aussehen mag, zeigt der Musterabgleich seine Stärke erst, wenn du auch andere Muster verwendest. Ein solches Muster ist das Variablenmuster, mit dem du einen Wert erfassen kannst:
match number with
| 0 -> "Zero"
| i -> sprintf "Non zero: %d" i
In manchen Fällen möchtest du einem Muster eine zusätzliche Bedingung hinzufügen. Das nennt man eine Wächterklausel, die du mit dem when-Schlüsselwort hinzufügen kannst:
match number with
| 0 -> "Zero"
| i when i < 0 -> "Negative number"
Eine Wächterklausel kann ein beliebiger gültiger Ausdruck sein, auch der Aufruf einer Funktion.
Im obigen Beispiel passt nicht jede mögliche Eingabe auf ein Muster. Der Compiler erkennt das und gibt eine Warnung aus. Das nennt man vollständigen Musterabgleich. Um die Warnung loszuwerden, musst du alle Fälle behandeln. Dafür kannst du das [Platzhaltermuster][wildcard-pattern] verwenden, ein Muster, das auf jeden Wert passt:
match number with
| i when i < 0 -> "Negative number"
| _ -> "Positive number"
// No compiler warning
Beachte, dass der Compiler when-Klauseln nicht verwenden kann, um die Vollständigkeit abzuleiten:
match number with
| i when i < 0 -> "Negative number"
| i when i >= 0 -> "Positive number"
// Compiler warning
Der Musterabgleich prüft einen Wert von oben nach unten gegen jedes Muster, bis er ein passendes Muster findet, und führt dann die zugehörige Logik aus. Die Reihenfolge der Muster ist wichtig! Deshalb sollte das Platzhaltermuster immer das letzte Muster in einem match-Ausdruck sein.
So mächtig der Musterabgleich auch ist, einfache bedingte Logik lässt sich mit einem if/else-Ausdruck meist klarer ausdrücken:
let usingPatternMatching number =
match number with
| 0 -> "Zero"
| _ -> "Non-zero"
let usingIfElse number = if number = 0 then "Zero" else "Non-zero"