Lecciones del módulo (1/2)
Genéricos y funciones
Los generics (tipos genéricos) permiten escribir código flexible y reutilizable, evitando la duplicación de lógica para diferentes tipos de datos. En lugar de definir múltiples funciones o estructuras para tipos diferentes (como i32, f64 o String), podemos usar un parámetro de tipo genérico, indicado convencionalmente con la letra T.
El compilador de Rust gestiona los generics mediante un proceso llamado monomorfización: durante la compilación, el compilador genera una copia del código genérico para cada tipo concreto con el que se utiliza realmente. De esta manera, no hay sobrecarga de rendimiento en tiempo de ejecución.
Funciones Genéricas
Para definir una función genérica, colocamos el parámetro de tipo <T> inmediatamente después del nombre de la función y antes de la lista de parámetros:
fn print_value<T: std::fmt::Debug>(value: T) {
println!("Valore: {:?}", value);
}
En las funciones genéricas, podemos usar el tipo genérico T tanto para los tipos de los argumentos como para el tipo de retorno:
fn identity<T>(value: T) -> T {
value
}
Estructuras Genéricas
También podemos utilizar los parámetros de tipo genérico dentro de las estructuras de datos (struct) para definir campos flexibles:
struct KeyValuePair<K, V> {
key: K,
value: V,
}
fn main() {
let pair = KeyValuePair {
key: String::from("eta"),
value: 30,
};
}
En el bloque impl para una struct genérica, debemos declarar el parámetro de tipo <T> inmediatamente después de la palabra clave impl para indicar que estamos implementando métodos sobre una estructura genérica:
struct Container<T> {
value: T,
}
impl<T> Container<T> {
fn new(value: T) -> Self {
Container { value }
}
fn value(&self) -> &T {
&self.value
}
}
Pruébalo tú
Ejercicio 1: La estructura Point
Define una estructura genérica llamada Point<T> con dos campos: x de tipo T y y de tipo T. En el main, instancia una variable point que contenga un Point con valores x igual a 5 y y igual a 10 (enteros), luego imprime en pantalla el valor de point.x.
Mostrar pista
Declara la struct usando `struct Point<T> { x: T, y: T }`. Instánciala en el main y usa `point.x` para imprimirla.
Solución disponible después de 3 intentos
Ejercicio 2: Inversión de una Tupla con swap
Escribe una función genérica llamada swap<T> que acepte como entrada una tupla de dos elementos (T, T) y devuelva una nueva tupla (T, T) con los elementos invertidos de posición. En el main, llama a la función con la tupla (1, 2) e imprime el resultado.
Mostrar pista
La firma de la función debe ser `fn swap<T>(pair: (T, T)) -> (T, T)`. Devuelve la tupla invertida con `(pair.1, pair.0)`.
Solución disponible después de 3 intentos
Ejercicio 3: La estructura Container
Define una struct genérica Container<T> que contenga un campo value de tipo T. Implementa un bloque impl genérico para definir un método new que acepte un valor de tipo T y devuelva una instancia de Container<T>.
Mostrar pista
Usa `impl<T> Container<T>`para implementar el método asociado`fn new(value: T) -> Self { Container { value } }`.
Solución disponible después de 3 intentos