flakolefluk.dev

Aprendiendo Rust en público - Funciones (4)

La última vez les comenté que me tenía la idea de crear un PR (Pull Request) en el repositorio de rustlings.

Por si no recuerdan, éste era el ejercicio (completado).

// functions3.rs
fn main() {
call_me(3);
}

fn call_me(num: i32) { // <--- esta línea es la que me pareció cuestionable
for i in 0..num {
println!("Ring! Call number {}", i + 1);
}
}

Me parecía un poco fuera de lugar poder iterar sobre un número negativo (i32 permite valores tanto negativos como positivos).

Bueno, esa duda se convirtio en este PR. que ya fue aceptado y es parte de rustlings!

Pueden ver que el cambio es mínimo, pero los PRs no tienen porque ser grandes cambios.

Ahora soy parte de la lista de personas que contribuyen a rustlings. XD

Luego de esta pequeña demostración de felicidad, sigamos con los ejercicios.

// functions4.rs
// Make me compile! Execute `rustlings hint functions4` for hints :)

// This store is having a sale where if the price is an even number, you get
// 10 Rustbucks off, but if it's an odd number, it's 3 Rustbucks off.

// I AM NOT DONE

fn main() {
let original_price = 51;
println!("Your sale price is {}", sale_price(original_price));
}

fn sale_price(price: i32) -> {
if is_even(price) {
price - 10
} else {
price - 3
}
}

fn is_even(num: i32) -> bool {
num % 2 == 0
}

Damos una mirada al error del compilador.

⚠️  Compiling of exercises/functions/functions4.rs failed! Please try again. Here's the output:
error: expected type, found `{`
--> exercises/functions/functions4.rs:14:30
|
14 | fn sale_price(price: i32) -> {
| ^ expected type

error: aborting due to previous error

Nos indica que el error está en que esperaba que declararamos un tipo después de la flecha.
Para comprender qué significa esto, vamos a la documentación de Rust.

Para declarar una función que retorna algo la forma de hacerlo sería fn <NOMBRE_DE_LA_FUNCION>(<ARGUMENTOS>) -> <TIPO DE VALOR DE RETORNO>.

Esto coincide con el error del compilador. Nos falta el tipo del valor de retorno.
Podemos ver un ejemplo de una función bien declarada en la función is_even del mismo ejercicio.

Para corregirlo entonces necesitamos ver el tipo de valor que retornará y agregarlo a la declaración de la función.

Demos una mirada más en detalle a la función en particular.

fn sale_price(price: i32) -> {
if is_even(price) {
price - 10
} else {
price - 3
}
}

He aquí algo que como desarrollador trabajando casi exclusivamente con JS me sorprendió más (hasta ahora).
En JS, para retornar un valor hay que expresarlo claramente con la palabra return.
En JS, usar o no punto y coma (;) es opcional.
En Rust, esto cambia y tiene implicancias importantes.

Nuevamente vamos al libro de Rust

Tomar nota:

Luego, price - 3 y price + 3; son cosas distintas. (aquí es donde explota mi cerebro).

Una función retornará el valor de la última expresión que haya dentro de ella, o puede retornar antes usando el keyword return.

Volvamos al ejercicio:
Si is_even(price) retorna true o verdadero, la última expresión será price - 10 (nótese que no lleva ;). De otre forma la última expresión será price - 3.

De esto deducimos que el valor retornado será de tipo i32.

Nuestro ejercicio entonces queda así:


fn main() {
let original_price = 51;
println!("Your sale price is {}", sale_price(original_price));
}

fn sale_price(price: i32) -> i32 {
if is_even(price) {
price - 10
} else {
price - 3
}
}

fn is_even(num: i32) -> bool {
num % 2 == 0
}

Nuestro ejercicio está ahora correcto!.

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