En Rust, la distinción entre una sentencia (statement) y una expresión (expression) es el pilar que define cómo se fluye la información. Una sentencia es una instrucción que realiza una acción pero no devuelve un valor (técnicamente, devuelve el tipo unitario ()). Una expresión, en cambio, es algo que evalúa y produce un valor.
Casi todo en Rust es una expresión. Esto permite que bloques de código, estructuras de control como if o match, e incluso bucles loop, puedan ser asignados directamente a variables. Por ejemplo, un bloque de código encerrado entre llaves { ... } es una expresión cuyo valor es el resultado de la última línea, siempre y cuando esa última línea no tenga un punto y coma ;.
El uso del punto y coma es el interruptor que transforma una expresión en una sentencia. Si colocas un ; al final de una línea, le estás diciendo al compilador: “calcula este valor, pero descártalo y devuelve ()“. Esto hace que el código sea más declarativo y reduce la necesidad de crear variables temporales innecesarias. Sin embargo, esto impone una regla estricta: cuando usas una estructura como if o match como expresión, todos los posibles caminos deben devolver exactamente el mismo tipo de dato. Si un brazo devuelve un i32 y otro un String, el compilador generará un error.
fn main() {
// 1. Bloques como expresiones
// El bloque devuelve el valor de la última línea sin punto y coma
let suma = {
let a = 10;
let b = 20;
a + b // Expresión: devuelve 30
};
let condicion = true;
// 2. 'if' como expresión
// Ambos brazos deben devolver el mismo tipo (&str en este caso)
let mensaje = if condicion {
"Todo bien" // Expresión
} else {
"Algo falló" // Expresión
};
// 3. 'match' como expresión
let categoria = match suma {
0..=15 => "Pequeño",
_ => "Grande",
};
// 4. Diferencia entre expresión y sentencia
let _valor_sentencia = {
let x = 5;
x + 5; // Con punto y coma, esto es una sentencia que devuelve ()
};
println!("Suma: {}, Mensaje: {}, Categoria: {}", suma, mensaje, categoria);
}
Explicación del Código
* suma: Se asigna mediante un bloque { ... }. Como la última instrucción a + b no tiene ;, el bloque actúa como una expresión que evalúa la suma y devuelve 30.
* condicion: Es una variable booleana utilizada para controlar el flujo del siguiente bloque.
* mensaje: Aquí if actúa como una expresión. El compilador garantiza que tanto el brazo del if como el del else devuelvan un tipo &str. Si uno de ellos tuviera un punto y coma extra, el código no compilaría porque el tipo sería () en lugar de &str.
* categoria: El bloque match evalúa el valor de suma. Dependiendo del patrón que coincida, devuelve una expresión de tipo &str.
* _valor_sentencia: Al añadir un ; después de x + 5, la expresión se convierte en una sentencia. El valor 10 se descarta y la variable _valor_sentencia almacena el tipo unitario ().
N° 18