Por que o Rust não tem argumentos padrão — e como contornar isso
\n\nSe você veio para o Rust do Python, JavaScript ou C++, provavelmente encontrou uma surpresa: o Rust não tem suporte embutido para argumentos padrão. Você não pode simplesmente escrever fn greet(name = "mundo") — o compilador dirá "não".
Mas não se preocupe! O Rust oferece outras abordagens, mais flexíveis e seguras. Neste tutorial, vamos analisar 3 maneiras comprovadas de implementar o comportamento de argumentos padrão. Você aprenderá a usar Option<T>, estruturas com configurações e o padrão Builder — e qual método escolher para sua tarefa.
O artigo é baseado em uma pergunta real do Stack Overflow (mais de 50.000 visualizações) — adaptamos para um formato educacional. Vamos lá!
\n\nMétodo 1. Usando Option<T> — a opção mais simples
\n\nA maneira mais direta é aceitar argumentos como Option<T> e, dentro da função, substituir pelos valores padrão.
fn greet(name: Option<&str>) {\n let name = name.unwrap_or("mundo");\n println!("Olá, {}!", name);\n}\n\nfn main() {\n greet(Some("Ana")); // Olá, Ana!\n greet(None); // Olá, mundo!\n}\n\n\nVantagens:
\n- \n
- Mínimo de código \n
- Claro até para iniciantes \n
- Não requer estruturas adicionais \n
Desvantagens:
\n- \n
- Cada chamada requer encapsulamento em
Some(...)ouNone\n - Se houver vários parâmetros, o código se torna verboso \n
Esta abordagem é ideal para funções com 1-2 parâmetros opcionais. Mas se houver mais, a legibilidade sofre.
\n\nMétodo 2. Estrutura com configurações — limpo e escalável
\n\nQuando os parâmetros se tornam 3, 5 ou 10, uma estrutura de configuração vem em socorro. Você cria um tipo separado que armazena todas as configurações e implementa o trait Default para ele.
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: "Olá".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 // Usando valores padrão\n greet(GreetConfig::default());\n // Saída: Olá, mundo!\n\n // Alterando apenas o necessário\n greet(GreetConfig {\n name: "Ana".to_string(),\n ..Default::default()\n });\n // Saída: Olá, Ana!\n\n // Chamada totalmente personalizada\n greet(GreetConfig {\n name: "Mundo".to_string(),\n greeting: "Olá".to_string(),\n excitement_level: 3,\n });\n // Saída: Olá, Mundo!!!\n}\n\n\nVantagens:
\n- \n
- Máxima flexibilidade \n
- Você pode adicionar novos campos sem alterar a assinatura da função \n
- A sintaxe
..Default::default()é muito legível \n
Desvantagens:
\n- \n
- Requer mais código boilerplate \n
- Você precisa implementar explicitamente o trait
Default\n
Esta é a escolha ideal para projetos reais: bibliotecas, funções de configuração, APIs complexas.
\n\nMétodo 3. Builder Pattern — para quem gosta de encadeamento
\n\nO padrão Builder é um clássico do ecossistema Rust. Você cria uma estrutura construtora que acumula parâmetros e, no final, chama o método build().
struct Greeter {\n name: String,\n greeting: String,\n excitement_level: u8,\n}\n\nstruct GreeterBuilder {\n nam