¿Por qué "romper" no necesita un punto y coma al finalizar un "bucle"?
Extracto del Capítulo 3.5 del Libro de Rust:
... usamos la
break
palabra clave con el valorcounter * 2
. Después del ciclo, usamos un punto y coma para finalizar la declaración que asigna el valor aresult
.
Más el fragmento de código:
fn main() {
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
}
};
println!("The result is {}", result);
}
Entiendo cómo funciona esto y por qué el resultado es 20, pero noté que si quito el punto y coma en la línea que contiene la palabra clave "break", el programa es equivalente.
¿Por qué el punto y coma es opcional en este caso?
Respuestas
Un ejemplo más breve:
let _: i32 = loop {
if true {
break 3; // ()
}
};
Ese es solo otro ejemplo en el que el punto y coma no interfiere con el resultado esperado. Por un lado, la inserción de un punto y coma introduce una declaración de expresión, que evalúa el tipo de unidad ()
. A medida que las expresiones loop
sy if
continúan admitiendo un bloque de código que se evalúa con el mismo tipo ()
, todos los tipos están en conformidad.
let _: i32 = loop {
if true {
break 3 // !
}
};
Si se quita el punto y coma, break
se evalúa al tipo nunca! , que coacciona a cualquier otro tipo. Esto significa que cumplirá con cualquier tipo esperado por el alcance externo. Así que todo está bien de todos modos, siempre que no intente agregar ninguna otra declaración antes del final del bloque if.
Ambos break
y return
evalúan !
, ya que sus efectos secundarios implican que el programa no seguirá el flujo de trabajo natural.
Ver también:
- ¿Por qué las expresiones de retorno usan punto y coma cuando no son necesarias?
- ¿Cuál es la diferencia entre usar la declaración de retorno y omitir el punto y coma en Rust?
- Cómo afirmar estáticamente que el final de una función es inalcanzable
La referencia del lenguaje Rust sobre declaraciones de expresión :
Una declaración de expresión es aquella que evalúa una expresión e ignora su resultado. Como regla, el propósito de una declaración de expresión es activar los efectos de evaluar su expresión.
Una expresión que consta solo de una expresión de bloque o una expresión de flujo de control, si se usa en un contexto donde se permite una declaración, puede omitir el punto y coma al final .
Me imagino que esto es puramente por estética y ergonomía, ya que casi todo es expresión en Rust. Si el punto y coma al final fuera obligatorio después de todas las expresiones, entonces tendríamos que terminar los bloques if-else (que también son expresiones) con punto y coma, lo que se ve terrible:
if {
// do something
} else {
// do something else
}; // <- gross
De manera similar, podemos omitir el punto y coma al final de todas las expresiones de flujo de control porque producen un flujo de control, por lo que la función típica del punto y coma, que es descartar el resultado de la expresión y evaluar en su ()
lugar, se vuelve irrelevante.
fn five() -> i32 {
return 5 // to semicolon or not to semicolon? it doesn't matter
}
En el ejemplo anterior, no importa si terminamos return 5
con un punto y coma o no, ya que nada puede "capturar" el resultado de esa expresión de todos modos, ya que produce un flujo de control. Lo mismo sería cierto para otras expresiones de flujo de control como break
y continue
.