flakolefluk.dev

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:

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.

¡¡¡A la próxima nos encontramos con el quiz nº1!!!

Para seguir esta serie, puedes buscar por el tag #aprendiendo_rust