Aprendiendo Rust en público - If (2)
Continuamos con la sección de la expresión if.
Vamos con el segundo ejercicio (y final) de esta parte.
// if2.rs
pub fn fizz_if_foo(fizzish: &str) -> &str {
if fizzish == "fizz" {
"foo"
} else {
1
}
}
// No test changes needed!
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn foo_for_fizz() {
assert_eq!(fizz_if_foo("fizz"), "foo")
}
#[test]
fn bar_for_fuzz() {
assert_eq!(fizz_if_foo("fuzz"), "bar")
}
#[test]
fn default_to_baz() {
assert_eq!(fizz_if_foo("literally anything"), "baz")
}
}
Revisemos el error:
⚠️ Compiling of exercises/if/if2.rs failed! Please try again. Here's the output:
error[E0308]: mismatched types
--> exercises/if/if2.rs:13:9
|
13 | 1
| ^ expected `&str`, found integer
error: aborting due to previous error
Por supuesto, nuevamente tenemos un error de tipo en la función fizz_if_foo
, que espera que el valor retornado sea de tipo &str
.
Si la función es verdadera, retornaremos el literal foo
que cumple con el tipo requerido. Sin embargo la rama else
retorna 1
, por lo que tenemos un error de compilado.
Podríamos solucionar el error de compilación de compilador cambiando el valor 1
por "wiii"
por ejemplo.
Veamos que sucede.
pub fn fizz_if_foo(fizzish: &str) -> &str {
if fizzish == "fizz" {
"foo"
} else {
"wiii"
}
}
Compila, pero tenemos un error de un tipo nuevo para nuestros ejercicios hasta ahora.
⚠️ Testing of exercises/if/if2.rs failed! Please try again. Here's the output:
running 3 tests
test tests::foo_for_fizz ... ok
test tests::bar_for_fuzz ... FAILED
test tests::default_to_baz ... FAILED
successes:
successes:
tests::foo_for_fizz
failures:
---- tests::bar_for_fuzz stdout ----
thread 'tests::bar_for_fuzz' panicked at 'assertion failed: `(left == right)`
left: `"wiii"`,
right: `"bar"`', exercises/if/if2.rs:29:9
---- tests::default_to_baz stdout ----
thread 'tests::default_to_baz' panicked at 'assertion failed: `(left == right)`
left: `"wiii"`,
right: `"baz"`', exercises/if/if2.rs:34:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
tests::bar_for_fuzz
tests::default_to_baz
test result: FAILED. 1 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out
Error en los tests! Ahora toman sentido los tests al final del ejercicio.
Nos darán una pista del resultado al que debemos llegar.
No voy a profundizar mucho en los tests en este momento.
Pero debemos poder entender lo que se espera.
Cada tests está precedido por #[test], y en cada test estamos verificando que dos valores sean iguales, usando el macro assert_eq!
(prometo escribir más sobre tests).
El primer test pasó correctamente por que el resultado de fizz_if_foo("fizz")
fue efectivamente foo
. Lo cual coincide con lo que esperamos del codigo (la condición es verdadera).
El segundo test falló. El test esperaba que fizz_if_foo("fuzz")
retornara bar
. Ajá! En nuestro intento por compilar el código, retornamos wiii
en caso de que el argumento no fuera "fizz" (caso else
). Entonces modifiquemos el código para que retorne bar
en el caso de que la condición sea falsa.
Otro error:
⚠️ Testing of exercises/if/if2.rs failed! Please try again. Here's the output:
running 3 tests
test tests::bar_for_fuzz ... ok
test tests::foo_for_fizz ... ok
test tests::default_to_baz ... FAILED
successes:
successes:
tests::bar_for_fuzz
tests::foo_for_fizz
failures:
---- tests::default_to_baz stdout ----
thread 'tests::default_to_baz' panicked at 'assertion failed: `(left == right)`
left: `"bar"`,
right: `"baz"`', exercises/if/if2.rs:34:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
tests::default_to_baz
test result: FAILED. 2 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
Ahora el primer y segundo test pasaron, pero el tercero falló.
Revisamos el tercer test y dice que si el argumento de la función es "literalmente cualquier cosa", debo retornar baz
.
Entonces nos encontramos con un tercer caso posible o una tercera rama.
Anteriormente hablamos de if
y else
, pero eso nos deja solo dos posibles ramas. Existe otra expresión intermedia que nos permite agregar cuantos casos posibles queramos: else if <condición>
. Esta expresión siempre debe ir precedida de una expresión if
y opcionalmente terminar con un else
.
Tenemos entonces:
- caso a: si "fizz" entonces "foo"
- caso b: si "fuzz" entonces "bar"
- caso c: si cualquier otra cosa entonces "baz"
Modifiquemos nuestro código y veamos la expresión else if
en acción.
// if2.rs
pub fn fizz_if_foo(fizzish: &str) -> &str {
if fizzish == "fizz" {
"foo"
} else if fizzish == "fuzz" {
"bar"
} else {
"baz"
}
}
Ahora sí. El ejercicio compila y los tests pasan. ¡Excelente!
Un resumen de la sección.
- La expresión if divide el flujo del código en ramas.
- se construye de la siguiente forma:
if <condición>
- podemos agregar n ramas, con la expresión
else if <condición>
- opcionalmente puede haber una rama
else
que responde si las condiciones delif
y loselse if
son falsas.
¡¡¡A la próxima nos encontramos con el quiz nº1!!!
Para seguir esta serie, puedes buscar por el tag #aprendiendo_rust
- Anterior: Aprendiendo Rust en público - If (1)