El control de flujo es la forma de decidir qué instrucciones ejecutar y en qué orden.
Hasta ahora, nuestros programas han sido una línea recta: se ejecutan de arriba a abajo, instrucción tras instrucción. El software real necesita tomar decisiones: “si el usuario está logueado, muestra el panel; si no, muestra el login”.
Para esto utilizamos el control de flujo. Si vienes de C, Java o JavaScript, la sintaxis de if y else te resultará muy familiar, pero en Rust hay un detalle importante: es una expresión, no una sentencia.
Hoy vamos a ver cómo escribir condiciones y cómo aprovechar esa característica para escribir código más limpio y conciso.
La sintaxis básica: if
La estructura más básica es el bloque if. La sintaxis es muy parecida a otros lenguajes, con dos pequeñas diferencias estéticas:
- No hacen falta paréntesis
()alrededor de la condición. - Las llaves
{}son obligatorias siempre (incluso si solo hay una línea de código dentro).
fn main() {
let numero = 7;
if numero < 10 {
println!("El número es pequeño");
} else {
println!("El número es grande");
}
}Múltiples condiciones: else if
Podemos encadenar varias condiciones de la forma habitual.
let numero = 6;
if numero % 4 == 0 {
println!("Es divisible por 4");
} else if numero % 3 == 0 {
println!("Es divisible por 3");
} else if numero % 2 == 0 {
println!("Es divisible por 2");
} else {
println!("No es divisible por 4, 3 ni 2");
}Si tienes demasiados else if encadenados, el código se vuelve difícil de leer. En Rust, cuando tenemos muchas ramas, solemos preferir usar la estructura match, que veremos en profundidad más adelante.
if como expresión
En la mayoría de lenguajes, if es una sentencia (statement). Es una instrucción que hace algo, pero no “devuelve” nada.
En Rust, if es una expresión (expression). Significa que al ejecutarse, devuelve un valor. Es decir, nos permite asignar el resultado de un if directamente a una variable.
Asignación condicional
Imagina que quieres asignar un valor a una variable dependiendo de una condición. En otros lenguajes harías esto:
// Estilo JavaScript (imperativo)
let condicion = true;
let x;
if (condicion) {
x = 5;
} else {
x = 6;
}En Rust, podemos hacerlo de forma mucho más elegante:
// Estilo Rust (expresión)
fn main() {
let condicion = true;
let x = if condicion { 5 } else { 6 };
println!("El valor de x es: {}", x);
}Analicemos qué acaba de pasar:
- Declaramos
let x =. - Evaluamos el bloque
if. - Si es
true, el bloque devuelve5. - Si es
false, el bloque devuelve6. - Ese resultado se asigna a
x.
Fíjate en que los números 5 y 6 dentro de las llaves no llevan punto y coma. Esto es porque queremos retornarlos (recuerda: en Rust, la última línea sin ; es el valor de retorno).
¿Dónde está el operador ternario?
Muchos preguntan por el operador ternario condicion ? valor1 : valor2 de C/JS.
En Rust no existe porque no hace falta. if else ya funciona como un operador ternario, pero más legible.
Coherencia de tipos
Como estamos asignando el resultado a una variable (x), Rust necesita saber de qué tipo es x. Por tanto, todas las ramas del if deben devolver el mismo tipo de dato.
El siguiente código no compila:
let condicion = true;
// ❌ Error: `if` and `else` have incompatible types
let numero = if condicion {
5 // Esto es un entero (i32)
} else {
"seis" // Esto es una cadena (&str)
};Rust nos dará el error E0308. No puede crear una variable que a veces sea un número y a veces un texto (para eso necesitaríamos un enum, que veremos luego).