Una expresión if/elif/else sirve para ejecutar lógica de forma condicional. F# también tiene otra forma más potente de ejecutar lógica de manera condicional: la coincidencia de patrones. Con la coincidencia de patrones, se puede comparar un valor con uno o varios patrones. Un ejemplo de patrón es el patrón constante, que compara un valor con una constante (por ejemplo, 1 o "hello").
En F#, la coincidencia de patrones se hace mediante la palabra clave match:
let describe number =
match number with
| 0 -> "Zero"
| 1 -> "One"
Aunque esto pueda parecer una instrucción switch de otros lenguajes, la coincidencia de patrones empieza a brillar cuando además se usan otros patrones. Uno de estos patrones es el patrón de variable, que permite capturar un valor:
match number with
| 0 -> "Zero"
| i -> sprintf "Non zero: %d" i
En algunos casos, puede que quieras añadir una condición adicional a un patrón. Esto se conoce como cláusula de guarda, y se puede añadir con la palabra clave when:
match number with
| 0 -> "Zero"
| i when i < 0 -> "Negative number"
Una cláusula de guarda puede ser cualquier expresión válida, lo que incluye llamar a funciones.
En el ejemplo anterior, no todas las entradas posibles tendrán un patrón que coincida. El compilador lo detectará y mostrará una advertencia. Esto se conoce como coincidencia exhaustiva. Para resolver la advertencia, hay que cubrir todos los casos. Para ello se puede usar el [patrón comodín][wildcard-pattern], que es un patrón que coincide con cualquier valor:
match number with
| i when i < 0 -> "Negative number"
| _ -> "Positive number"
// No compiler warning
Ten en cuenta que el compilador no puede usar cláusulas when para inferir la exhaustividad:
match number with
| i when i < 0 -> "Negative number"
| i when i >= 0 -> "Positive number"
// Compiler warning
La coincidencia de patrones compara un valor con cada patrón de arriba abajo, hasta encontrar un patrón que coincida y ejecutar la lógica asociada a ese patrón. ¡El orden de los patrones importa! Por lo tanto, el patrón comodín debe ser siempre el último patrón de una expresión match.
Aunque la coincidencia de patrones es muy potente, la lógica condicional simple suele expresarse con más claridad usando una expresión if/else:
let usingPatternMatching number =
match number with
| 0 -> "Zero"
| _ -> "Non-zero"
let usingIfElse number = if number = 0 then "Zero" else "Non-zero"