Match en Rust: rangos, patrones y expresiones

Resumen

La estructura match en Rust te permite tomar decisiones según el valor de una variable de forma más limpia y potente que un encadenamiento de if else. Es ideal para programadores que ya dominan condicionales básicos y quieren escribir código más expresivo en Rust.

Antes de entrar al detalle, ten presente el contexto: en la clase anterior se instaló Actix, se creó un Hola, mundo y se conectó la base de datos. Aquí hacemos una pausa para entender una pieza que vas a usar todo el tiempo cuando trabajes con validaciones, Results y Options.

¿Por qué usar match en lugar de if else en Rust?

Cuando tienes muchas opciones distintas para una misma variable, llenar el código de if else deja de ser óptimo. Lenguajes como C, Java o JavaScript resuelven esto con case. Rust va más allá con match, que es parecido pero mucho más potente porque combina varios tipos de patrones y, además, devuelve valores.

La idea es simple: declaras la palabra reservada match, le pasas la variable que quieres evaluar y dentro de las llaves describes los patrones que te interesan. Cada patrón apunta con una flecha a la acción o valor que corresponde.

¿Qué es match en Rust? Es una estructura de control que compara una variable contra varios patrones y ejecuta el bloque del primer patrón que coincida. Funciona como un switch case, pero más estricto y expresivo.

¿Cómo se escribe un match básico con patrones en Rust?

El patrón más simple es la coincidencia exacta. Si declaras let edad y quieres reaccionar a valores específicos, escribes algo así:

rust match edad { 18 => println!("Tienes 18 años, apenas puedes entrar"), 17 => println!("Todavía no puedes entrar, pero falta poco"), _ => println!("Tu edad aún no está programada"), }

Fíjate en tres detalles. Primero, cada brazo termina en coma. Segundo, si quieres ejecutar varias acciones en un mismo brazo, abres llaves y dentro puedes poner varios println separados por punto y coma. Tercero, Rust te obliga a cubrir todos los casos posibles. Si no lo haces, el compilador marca error.

¿Qué significa el guion bajo en un match?

El guion bajo (_) es el caso por defecto. Captura cualquier valor que no haya coincidido con los patrones anteriores y es la forma estándar de cerrar un match exhaustivo. Sin él, el código no compila cuando trabajas con tipos que tienen muchos valores posibles, como un entero.

¿Cómo se manejan rangos y patrones or en match?

Aquí es donde match empieza a brillar frente a un if else tradicional. Puedes evaluar un rango completo de valores en una sola línea o combinar varios valores con el patrón or.

  • Rango inclusivo: con la sintaxis 0..=16 cubres todas las edades de 0 a 16. Útil para clasificar grupos enteros sin escribir un brazo por valor.
  • Patrón or: con 19 | 20 | 21 atiendes varias coincidencias en un solo brazo. Ideal cuando distintos valores comparten la misma respuesta.
  • Coincidencia exacta: sigue disponible para casos puntuales como 17 o 18.

Un ejemplo combinando los tres se vería así:

rust match edad { 0..=16 => println!("Aún eres menor de edad"), 17 => println!("Todavía no puedes entrar, pero falta poco"), 18 => println!("Tienes 18 años, apenas puedes entrar"), 19 | 20 | 21 => println!("Consume alcohol con moderación"), _ => println!("Tu edad aún no está programada"), }

Si pruebas con edad = 15, el programa responde con el mensaje de menor de edad. Con 20, te recuerda consumir alcohol con moderación. La lógica queda agrupada y leíble.

¿Se puede usar match como expresión para asignar variables?

Sí, y aquí es donde Rust se diferencia de otros lenguajes. Un match no solo ejecuta acciones: también puede devolver un valor que asignas directamente a una variable. Esto convierte la estructura en una expresión, no solo en un bloque de control.

En lugar de imprimir dentro de cada brazo, devuelves el string o el dato que necesites:

rust let mensaje_edad = match edad { 0..=16 => "Aún eres menor de edad", 17 => "Todavía no puedes entrar, pero falta poco", 18 => "Tienes 18 años, apenas puedes entrar", 19 | 20 | 21 => "Consume alcohol con moderación", _ => "Tu edad aún no está programada", };

println!("El mensaje es {}", mensaje_edad);

Dos cosas para no olvidar: como estás declarando una variable, la sentencia completa termina con punto y coma, y todos los brazos deben devolver el mismo tipo de dato. Si un brazo devuelve un &str y otro un número, el compilador te lo va a reclamar.

¿Cuándo conviene usar match en vez de if else? Cuando tienes múltiples valores discretos, rangos o necesitas devolver un valor según el caso. También cuando trabajas con tipos como Option y Result, donde match obliga a manejar todas las variantes.

¿Dónde vas a usar match más adelante?

La potencia real de match aparece cuando lo combinas con tipos como Option (que puede ser nulo o tener valor) y Result (que puede ser error o valor correcto). Validar la respuesta de una base de datos, manejar errores de un endpoint o decidir el flujo según el estado de una petición se vuelve trivial con esta estructura.

En la siguiente clase vas a aplicar todo esto dentro del proyecto web con Actix. Mientras tanto, cuéntame en los comentarios en qué otra situación crees que match te resultaría útil. Te leo con atención.