Ir al contenido

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.

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ércoles
▶ Pruébalo tú mismo

El _ 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”.

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"),
}
}
▶ Pruébalo tú mismo

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"),
}
}
▶ Pruébalo tú mismo

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}");
}
▶ Pruébalo tú mismo

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!
▶ Pruébalo tú mismo

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 String necesita .as_str(). El texto escrito entre comillas, como "Ferris", es un &str. Si haces match de un String directamente contra él, Rust se detiene con error[E0308]: mismatched types ... expected String, found &str (tipos que no coinciden: esperaba un String y encontró un &str). Llamar a .as_str() te da una vista &str del String con 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().

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.

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ías
▶ Pruébalo tú mismo

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 servidor
▶ Pruébalo tú mismo
  • match compara 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 &str y con valores char; usa .as_str() para hacer match con un String.
  • match, como if, se puede usar como expresión para producir un valor.

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