Menu
Coddy logo textTech

Funciones genéricas

Parte de la sección Programación Orientada a Objetos del Journey de Rust de Coddy. Lección 27 de 61.

Los genéricos no se limitan a las estructuras. También puedes escribir funciones independientes que funcionen con cualquier tipo. Esto resulta útil cuando necesitas una función de utilidad que no pertenezca a una estructura específica, pero que siga siendo flexible.

La sintaxis refleja lo que has visto con las estructuras. Declara el parámetro genérico entre corchetes angulares después del nombre de la función, y después úsalo en los parámetros y en el tipo de retorno:

fn identity<T>(value: T) -> T {
    value
}

Esta función identity toma un valor de cualquier tipo y lo devuelve sin cambios. <T> declara el genérico, value: T lo acepta como parámetro y -> T especifica el tipo de retorno. Cuando llamas a la función, Rust infiere el tipo concreto:

let num = identity(42);        // T es i32
let text = identity("hello");  // T es &str

También puedes usar múltiples parámetros genéricos en las funciones, igual que con las estructuras:

fn make_pair<T, U>(first: T, second: U) -> (T, U) {
    (first, second)
}

let pair = make_pair(10, "ten");  // devuelve (i32, &str)

Las funciones genéricas te permiten escribir una lógica reutilizable una sola vez y aplicarla a muchos tipos, reduciendo la duplicación de código y manteniendo la seguridad de tipos.

challenge icon

Desafío

Fácil

¡Construyamos un módulo de utilidades con funciones genéricas que puedan trabajar con cualquier tipo! Crearás funciones independientes que demuestran cómo los genéricos hacen que tu código sea flexible y reutilizable sin estar ligado a una estructura específica.

Organizarás tu código en dos archivos:

  • utils.rs: Crea una colección de funciones de utilidad genéricas públicas:
    • wrap_in_pair<T>: recibe un único valor y devuelve una tupla que contiene ese valor dos veces: (value, value). Esto requiere que el tipo implemente Clone, así que usa <T: Clone>
    • swap<T, U>: recibe dos valores de tipos potencialmente diferentes y los devuelve en orden inverso como una tupla (U, T)
  • main.rs: Importa tu módulo de utilidades y demuestra estas funciones genéricas trabajando con diferentes tipos. Muestra cómo las mismas definiciones de funciones gestionan enteros, números de punto flotante y cadenas sin problemas.

En tu archivo principal, demuestra tus funciones de utilidad:

  1. Usa wrap_in_pair con un entero (la primera entrada, analizada como i32) e imprime ambos elementos
  2. Usa wrap_in_pair con una cadena (la segunda entrada) e imprime ambos elementos
  3. Usa swap con un entero (la tercera entrada, analizada como i32) y una cadena (la cuarta entrada); después, imprime el resultado intercambiado

Tu salida debe seguir este formato:

Pair of ints: ({value}, {value})
Pair of strings: ({value}, {value})
Swapped: ({string}, {int})

Por ejemplo, con las entradas 5, hello, 42 y world:

Pair of ints: (5, 5)
Pair of strings: (hello, hello)
Swapped: (world, 42)

Observa cómo wrap_in_pair funciona de forma idéntica tanto para enteros como para cadenas, y swap gestiona dos tipos completamente diferentes: ¡esa es la flexibilidad de las funciones genéricas!

Recibirás cuatro entradas: un entero, una cadena, otro entero y otra cadena.

Pruébalo tú mismo

mod utils;

use std::io;

fn main() {
    // Lee las cuatro entradas
    let mut input1 = String::new();
    io::stdin().read_line(&mut input1).expect("Failed to read line");
    let num1: i32 = input1.trim().parse().expect("Invalid integer");

    let mut input2 = String::new();
    io::stdin().read_line(&mut input2).expect("Failed to read line");
    let str1 = input2.trim().to_string();

    let mut input3 = String::new();
    io::stdin().read_line(&mut input3).expect("Failed to read line");
    let num2: i32 = input3.trim().parse().expect("Invalid integer");

    let mut input4 = String::new();
    io::stdin().read_line(&mut input4).expect("Failed to read line");
    let str2 = input4.trim().to_string();

    // TODO: Usa wrap_in_pair con num1 e imprime el resultado
    // Formato: Pair of ints: ({value}, {value})

    // TODO: Usa wrap_in_pair con str1 e imprime el resultado
    // Format: Pair of strings: ({value}, {value})

    // TODO: Usa swap con num2 y str2, luego imprime el resultado intercambiado
    // Formato: Swapped: ({string}, {int})
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de Rust online