Desestructurando Enums
Like tuples, structs and enums can also be destructured by matching:
Structs
struct Foo { x: (u32, u32), y: u32, } #[rustfmt::skip] fn main() { let foo = Foo { x: (1, 2), y: 3 }; match foo { Foo { x: (1, b), y } => println!("x.0 = 1, b = {b}, y = {y}"), Foo { y: 2, x: i } => println!("y = 2, x = {i:?}"), Foo { y, .. } => println!("y = {y}, other fields were ignored"), } }
Enums
Los patrones también se pueden usar para enlazar variables a partes de los valores. Así es como se inspecciona la estructura de tus tipos. Empecemos con un tipo enum
sencillo:
enum Result { Ok(i32), Err(String), } fn divide_in_two(n: i32) -> Result { if n % 2 == 0 { Result::Ok(n / 2) } else { Result::Err(format!("cannot divide {n} into two equal parts")) } } fn main() { let n = 100; match divide_in_two(n) { Result::Ok(half) => println!("{n} divided in two is {half}"), Result::Err(msg) => println!("sorry, an error happened: {msg}"), } }
Aquí hemos utilizado los brazos para desestructurar el valor de Result
. En el primer brazo, half
está vinculado al valor que hay dentro de la variante Ok
. En el segundo, msg
está vinculado al mensaje de error.
This slide should take about 10 minutes.
Structs
- Cambia los valores literales de
foo
para que coincidan con los demás patrones. - Añade un campo nuevo a
Foo
y realiza los cambios necesarios en el patrón. - La diferencia entre una captura y una expresión constante puede ser difícil de detectar. Prueba a cambiar el
2
del segundo brazo por una variable y observa que no funciona. Cámbialo aconst
y verás que vuelve a funcionar.
Enums
Puntos clave:
- La expresión
if
/else
devuelve una enumeración que más tarde se descomprime conmatch
. - Puedes probar a añadir una tercera variante a la definición de la enumeración y mostrar los errores al ejecutar el código. Señala los lugares en los que tu código está ahora incompleto y explica cómo el compilador intenta dar sugerencias.
- The values in the enum variants can only be accessed after being pattern matched.
- Demonstrate what happens when the search is inexhaustive. Note the advantage the Rust compiler provides by confirming when all cases are handled.
- Save the result of
divide_in_two
in theresult
variable andmatch
it in a loop. That won’t compile becausemsg
is consumed when matched. To fix it, match&result
instead ofresult
. That will makemsg
a reference so it won’t be consumed. This “match ergonomics” appeared in Rust 2018. If you want to support older Rust, replacemsg
withref msg
in the pattern.