Argumentos de función por defecto en Rust: soluciones elegantes sin sobrecargas

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Por qué Rust no tiene argumentos por defecto — y cómo solucionarlo

\n\n

Si vienes a Rust desde Python, JavaScript o C++, seguramente te has encontrado con una sorpresa: Rust no tiene soporte incorporado para argumentos por defecto. No puedes simplemente escribir fn greet(name = "mundo") — el compilador te dirá que no.

\n\n

¡Pero no te preocupes! Rust ofrece otros enfoques más flexibles y seguros. En este tutorial analizaremos 3 formas comprobadas de implementar el comportamiento de argumentos por defecto. Aprenderás a usar Option<T>, estructuras con configuración y el patrón Builder — y qué método elegir para tu tarea.

\n\n

El artículo está basado en una pregunta real de Stack Overflow (más de 50 000 visitas) — la hemos adaptado para un formato educativo. ¡Allá vamos!

\n\n

Método 1. Usamos Option<T> — la opción más simple

\n\n

La forma más directa es aceptar argumentos como Option<T> y dentro de la función sustituir valores por defecto.

\n\n
fn greet(name: Option<&str>) {\n    let name = name.unwrap_or("mundo");\n    println!("¡Hola, {}!", name);\n}\n\nfn main() {\n    greet(Some("Ana")); // ¡Hola, Ana!\n    greet(None);         // ¡Hola, mundo!\n}\n
\n\n

Ventajas:

\n
    \n
  • Mínimo código
  • \n
  • Comprensible incluso para principiantes
  • \n
  • No requiere estructuras adicionales
  • \n
\n\n

Desventajas:

\n
    \n
  • Cada llamada requiere envolver en Some(...) o None
  • \n
  • Si hay varios parámetros, el código se vuelve voluminoso
  • \n
\n\n

Este enfoque es ideal para funciones con 1-2 parámetros opcionales. Pero si hay más, la legibilidad se resiente.

\n\n

Método 2. Estructura con configuración — limpio y escalable

\n\n

Cuando los parámetros se convierten en 3, 5 o 10, una estructura de configuración viene al rescate. Creas un tipo separado que almacena toda la configuración e implementas el trait Default para él.

\n\n
struct GreetConfig {\n    name: String,\n    greeting: String,\n    excitement_level: u8,\n}\n\nimpl Default for GreetConfig {\n    fn default() -> Self {\n        Self {\n            name: "mundo".to_string(),\n            greeting: "Hola".to_string(),\n            excitement_level: 1,\n        }\n    }\n}\n\nfn greet(config: GreetConfig) {\n    let excitement = "!".repeat(config.excitement_level as usize);\n    println!("{}, {}{}", config.greeting, config.name, excitement);\n}\n\nfn main() {\n    // Usamos valores por defecto\n    greet(GreetConfig::default());\n    // Salida: ¡Hola, mundo!\n\n    // Cambiamos solo lo necesario\n    greet(GreetConfig {\n        name: "Ana".to_string(),\n        ..Default::default()\n    });\n    // Salida: ¡Hola, Ana!\n\n    // Llamada completamente personalizada\n    greet(GreetConfig {\n        name: "Mundo".to_string(),\n        greeting: "Saludos".to_string(),\n        excitement_level: 3,\n    });\n    // Salida: ¡Saludos, Mundo!!!\n}\n
\n\n

Ventajas:

\n
    \n
  • Máxima flexibilidad
  • \n
  • Se pueden añadir nuevos campos sin cambiar la firma de la función
  • \n
  • La sintaxis ..Default::default() es muy legible
  • \n
\n\n

Desventajas:

\n
    \n
  • Requiere más código boilerplate
  • \n
  • Hay que implementar explícitamente el trait Default
  • \n
\n\n

Esta es la elección ideal para proyectos reales: bibliotecas, funciones de configuración, APIs complejas.

\n\n

Método 3. Builder Pattern — para quienes aman las cadenas

\n\n

El patrón Builder es un clásico del ecosistema Rust. Creas una estructura constructora que acumula parámetros y al final llama al método build().

\n\n
struct Greeter {\n    name: String,\n    greeting: String,\n    excitement_level: u8,\n}\n\nstruct GreeterBuilder {\n    nam                

Blogs

Book Recommendations