Un'espressione if/elif/else può essere usata per eseguire della logica in modo condizionale. F# offre anche un altro modo, più potente, per eseguire della logica in modo condizionale: il pattern matching. Con il pattern matching, un valore può essere verificato rispetto a uno o più pattern. Un esempio di tale pattern è il pattern costante, che confronta un valore con una costante (ad esempio 1 o "hello").
In F#, il pattern matching si effettua tramite la parola chiave match:
let describe number =
match number with
| 0 -> "Zero"
| 1 -> "One"
Anche se può sembrare simile alle istruzioni switch di altri linguaggi, il pattern matching dà il meglio di sé quando si usano anche altri pattern. Uno di questi è il pattern variabile, che permette di catturare un valore:
match number with
| 0 -> "Zero"
| i -> sprintf "Non zero: %d" i
In alcuni casi, potresti voler aggiungere un'ulteriore condizione a un pattern. Questa è nota come guardia (clausola), e si può aggiungere con la parola chiave when:
match number with
| 0 -> "Zero"
| i when i < 0 -> "Negative number"
Una clausola di guardia può essere qualsiasi espressione valida, comprese le chiamate a funzioni.
Nell'esempio precedente, non tutti i possibili input avranno un pattern corrispondente. Il compilatore se ne accorgerà e produrrà un avviso. Questo è noto come pattern matching esaustivo. Per risolvere l'avviso, bisogna gestire tutti i casi. A questo scopo si può usare il [pattern jolly][wildcard-pattern], un pattern che corrisponde a qualsiasi valore:
match number with
| i when i < 0 -> "Negative number"
| _ -> "Positive number"
// No compiler warning
Tieni presente che il compilatore non può usare le clausole when per dedurre l'esaustività:
match number with
| i when i < 0 -> "Negative number"
| i when i >= 0 -> "Positive number"
// Compiler warning
Il pattern matching verifica un valore rispetto a ogni pattern, dall'alto verso il basso, finché non trova un pattern corrispondente ed esegue la logica associata a quel pattern. L'ordine dei pattern è importante! Perciò il pattern jolly dovrebbe essere sempre l'ultimo pattern di un'espressione match.
Anche se il pattern matching è molto potente, una semplice logica condizionale si può di solito esprimere in modo più chiaro con un'espressione if/else:
let usingPatternMatching number =
match number with
| 0 -> "Zero"
| _ -> "Non-zero"
let usingIfElse number = if number = 0 then "Zero" else "Non-zero"