Match en Rust
match compara un valor con una lista de patrones y ejecuta el código del que encaje. Si alguna vez usaste un switch, piensa en match como una versión más potente; y si no, igualmente es una de las herramientas más útiles que puedes aprender pronto.
match básico
Sección titulada «match básico»fn main() { let day = 3;
match day { 1 => println!("Lunes"), 2 => println!("Martes"), 3 => println!("Miércoles"), 4 => println!("Jueves"), 5 => println!("Viernes"), _ => println!("Fin de semana"), }}Salida:
MiércolesEl _ es un comodín: encaja con cualquier valor que no esté en la lista de arriba. match exige que se maneje cada valor posible, por eso suele haber un _ que cubre “todo lo demás”.
Varios valores a la vez
Sección titulada «Varios valores a la vez»Puedes agrupar varios valores en una sola rama usando |:
fn main() { let day = 6;
match day { 1 | 2 | 3 | 4 | 5 => println!("Día laborable"), 6 | 7 => println!("Fin de semana"), _ => println!("No es un día válido"), }}Con números, puedes cubrir un rango entero con ..=:
fn main() { let score = 85;
match score { 90..=100 => println!("A"), 75..=89 => println!("B"), 60..=74 => println!("C"), _ => println!("F"), }}match como expresión
Sección titulada «match como expresión»Igual que if, match puede producir un valor:
fn main() { let day = 6;
let kind = match day { 1 | 2 | 3 | 4 | 5 => "laborable", 6 | 7 => "fin de semana", _ => "desconocido", };
println!("{kind}");}Hacer match con texto y caracteres
Sección titulada «Hacer match con texto y caracteres»match no es solo para números. También funciona con string slices (&str) y con caracteres, y los rangos de caracteres como 'a'..='z' funcionan igual que los rangos de números:
fn main() { let command = "parar"; match command { "iniciar" => println!("Iniciando..."), "parar" | "salir" => println!("Deteniendo."), _ => println!("Comando desconocido: {command}"), }
let letter = 'k'; let kind = match letter { 'a' | 'e' | 'i' | 'o' | 'u' => "una vocal", 'a'..='z' => "una consonante", '0'..='9' => "un dígito", _ => "otra cosa", }; println!("'{letter}' es {kind}");
let name = String::from("Ferris"); match name.as_str() { "Ferris" => println!("¡Hola, cangrejo!"), _ => println!("¡Hola, {name}!"), }}Salida:
Deteniendo.'k' es una consonante¡Hola, cangrejo!Aquí hay dos cosas en las que vale la pena fijarse:
- El orden importa.
'a'también está dentro de'a'..='z', pero la rama de las vocales va primero, así que las vocales nunca llegan a la rama de las consonantes. Rust siempre elige la primera rama que encaja. - Un
Stringnecesita.as_str(). El texto escrito entre comillas, como"Ferris", es un&str. Si hacesmatchde unStringdirectamente contra él, Rust se detiene conerror[E0308]: mismatched types ... expected String, found &str(tipos que no coinciden: esperaba unStringy encontró un&str). Llamar a.as_str()te da una vista&strdelStringcon la que los patrones sí pueden compararse. (Mira la página de Strings para ver la diferencia entre los dos).
El match distingue entre mayúsculas y minúsculas: "Parar" no encajaría con "parar". Si el texto lo escribe un usuario, un truco habitual es hacer match sobre input.to_lowercase().as_str().
match o if/else
Sección titulada «match o if/else»Para comprobaciones sencillas de verdadero o falso sirven los dos, pero match empieza a ganar en cuanto tienes más de dos o tres posibilidades: se lee mejor que una larga cadena de else if, y el compilador comprueba que hayas cubierto todos los casos. Para una única condición de sí o no, if/else sigue siendo la herramienta adecuada.
Práctica
Sección titulada «Práctica»1. Días de un mes
Sección titulada «1. Días de un mes»Guarda el número de un mes en month (2). Usa match como expresión para calcular cuántos días tiene (sin contar los años bisiestos) e imprime El mes 2 tiene 28 días. Pista: los meses 1, 3, 5, 7, 8, 10 y 12 tienen 31 días; agrúpalos en una sola rama con |.
Ver solución
fn main() { let month = 2;
let days = match month { 1 | 3 | 5 | 7 | 8 | 10 | 12 => 31, 4 | 6 | 9 | 11 => 30, 2 => 28, _ => 0, // no es un mes real };
println!("El mes {month} tiene {days} días");}Salida:
El mes 2 tiene 28 días2. Códigos de estado HTTP
Sección titulada «2. Códigos de estado HTTP»Los servidores web responden con un número. Convierte un code en un significado corto: 200 es "OK", 404 es "No encontrado", cualquier otro de 400 a 499 es "Error del cliente", de 500 a 599 es "Error del servidor", y cualquier otro es "Desconocido". Pruébalo con 503. Pista: pon la rama exacta del 404 por encima del rango 400..=499, o nunca se llegará a ella.
Ver solución
fn main() { let code = 503;
let meaning = match code { 200 => "OK", 404 => "No encontrado", // tiene que ir antes del rango 400..=499 400..=499 => "Error del cliente", 500..=599 => "Error del servidor", _ => "Desconocido", };
println!("{code}: {meaning}");}Salida:
503: Error del servidorResumen
Sección titulada «Resumen»matchcompara un valor con patrones y ejecuta la rama que encaja.- Hay que manejar cada valor posible: usa
_como comodín. - Combina valores con
|, o cubre un rango con..=. - También puedes hacer match con texto
&stry con valoreschar; usa.as_str()para hacer match con unString. match, comoif, se puede usar como expresión para producir un valor.
Comprueba lo que aprendiste
Sección titulada «Comprueba lo que aprendiste»Comprueba lo aprendido
1. ¿Qué hace el patrón _ en un match?
2. ¿Qué pasa si un match no maneja todos los valores posibles y no tiene una rama _?
3. ¿Cómo cubres varios valores en una sola rama, como 1, 2 o 3?
Puntuación: 0 / 3
Para leer más
Sección titulada «Para leer más»- The match Control Flow Construct: The Rust Book (en inglés): el capítulo oficial, que también muestra
matchcon enums y conOption. - match: Rust by Example (en inglés): un ejemplo compacto y ejecutable con valores,
|, rangos y_. - Range patterns: The Rust Reference (en inglés): exactamente qué tipos y qué formas de rango puedes usar en un patrón.
- Match expressions: The Rust Reference (en inglés): las reglas precisas de las ramas, las guardas (guards) y cómo un
matchproduce su valor.