Flujo de Control Conciso con if let
La sintaxis if let
te permite combinar if
y let
en una forma menos
verbosa de manejar valores que coinciden con un patrón mientras se ignoran el
resto. Considera el programa en el Listado 6-6 que coincide con un valor
Option<u8>
en la variable config_max
pero solo quiere ejecutar el código si
el valor es la variante Some
.
fn main() { let config_max = Some(3u8); match config_max { Some(max) => println!("The maximum is configured to be {max}"), _ => (), } }
Si el valor es Some
, imprimimos el valor en la variante Some
vinculando el
valor a la variable max
en el patrón. No queremos hacer nada con el valor
None
. Para satisfacer la expresión match
, tenemos que agregar _ => ()
después de procesar solo una variante, lo cual es un código de plantilla
molesto para agregar.
En su lugar, podríamos escribir esto de una manera más corta usando if let
.
El siguiente código se comporta de la misma manera que el match
en el Listado
6-6:
fn main() { let config_max = Some(3u8); if let Some(max) = config_max { println!("The maximum is configured to be {max}"); } }
La sintaxis if let
toma un patrón y una expresión separados por un signo
igual. Funciona de la misma manera que un match
, donde la expresión se da al
match
y el patrón es su primer brazo. En este caso, el patrón es Some(max)
,
y el max
se vincula al valor dentro del Some
. Luego podemos usar max
en
el cuerpo del bloque if let
de la misma manera que usamos max
en el brazo
match
correspondiente. El código en el bloque if let
solo se ejecuta si el
valor coincide con el patrón.
Usar if let
significa menos escritura, menos indentación y menos código
repetitivo. Sin embargo, pierdes la verificación exhaustiva que hace cumplir
match
. Elegir entre match
e if let
depende de lo que estés haciendo en tu
situación particular y de si ser más conciso a cambio de la verificación
exhaustiva es un intercambio adecuado.
En otras palabras, puedes pensar en if let
como una sintaxis dulce para un
match
que ejecuta código cuando el valor coincide con un patrón y luego
ignora todos los demás valores.
Podemos incluir un else
con un if let
. El bloque de código que va con el
else
es el mismo que el bloque de código que iría con el caso _
en la
expresión match
que es equivalente al if let
y else
. Recuerda la
definición de Coin
en el Listado 6-4, donde la variante Quarter
también
tenía un valor UsState
. Si quisiéramos contar todas las monedas que no son
cuartos que vemos mientras también anunciamos el estado de los cuartos,
podríamos hacerlo con una expresión match
, como esta:
#[derive(Debug)] enum UsState { Alabama, Alaska, // --snip-- } enum Coin { Penny, Nickel, Dime, Quarter(UsState), } fn main() { let coin = Coin::Penny; let mut count = 0; match coin { Coin::Quarter(state) => println!("State quarter from {state:?}!"), _ => count += 1, } }
O podríamos usar un if let
y else
:
#[derive(Debug)] enum UsState { Alabama, Alaska, // --snip-- } enum Coin { Penny, Nickel, Dime, Quarter(UsState), } fn main() { let coin = Coin::Penny; let mut count = 0; if let Coin::Quarter(state) = coin { println!("State quarter from {state:?}!"); } else { count += 1; } }
Si se encuentra en una situación en la cual tu programa tiene lógica que es
demasiado verbosa para expresar usando un match
, recuerda que if let
está
en tu caja de herramientas de Rust también.
Resumen
Ahora hemos cubierto cómo usar enums para crear tipos personalizados que pueden
ser uno de un conjunto de valores enumerados. Hemos mostrado cómo el tipo
Option<T>
de la biblioteca estándar te ayuda a usar el sistema de tipos para
prevenir errores. Cuando los valores de enum tienen datos dentro de ellos,
podemos usar match
o if let
para extraer y usar esos valores, dependiendo de
cuántos casos necesites manejar.
Tus programas Rust ahora pueden expresar conceptos en tu dominio usando structs y enums. Crear tipos personalizados para usar en tu API asegura la seguridad de tipos: el compilador se asegurará de que tus funciones solo obtengan valores del tipo que cada función espera.
En orden de proveer una API bien organizada a tus usuarios que sea sencilla de usar y solo exponga exactamente lo que tus usuarios necesitarán, ahora vamos a ver los módulos de Rust.