Estruturas Condicionais: If e Match
A tomada de decisão é fundamental em qualquer programa. Em Rust, a estrutura if funciona de forma semelhante a outras linguagens, mas com uma característica única: é uma expressão, não apenas uma declaração. Isso significa que você pode atribuir o resultado de um if a uma variável.
fn main() {
let idade = 18;
// If como declaração
if idade >= 18 {
println!("Você é maior de idade");
} else if idade >= 13 {
println!("Você é adolescente");
} else {
println!("Você é criança");
}
// If como expressão
let categoria = if idade >= 18 { "adulto" } else { "menor" };
println!("Categoria: {}", categoria);
}
Rust também oferece o match, que é mais poderoso e seguro que o switch tradicional. O match força você a cobrir todos os casos possíveis, prevenindo bugs sutis. Ele é ideal quando você quer trabalhar com enums ou múltiplos padrões.
fn main() {
let numero = 3;
match numero {
1 => println!("Um"),
2 => println!("Dois"),
3 => println!("Três"),
_ => println!("Outro número"),
}
// Match com enums
enum Resultado {
Sucesso(String),
Erro(i32),
}
let resultado = Resultado::Sucesso("Operação concluída".to_string());
match resultado {
Resultado::Sucesso(msg) => println!("✓ {}", msg),
Resultado::Erro(codigo) => println!("✗ Código de erro: {}", codigo),
}
}
Loops: Estruturas de Repetição
Rust oferece três formas de criar loops, cada uma com seu propósito específico. O loop loop é uma repetição infinita que você controla com break. Use-o quando precisa sair do loop dinamicamente, com a flexibilidade de retornar um valor.
fn main() {
let mut contador = 0;
// Loop infinito com controle manual
loop {
contador += 1;
println!("Iteração: {}", contador);
if contador == 5 {
break; // Sai do loop
}
}
// Loop retornando um valor
let resultado = loop {
contador += 1;
if contador == 10 {
break contador * 2; // Retorna 20
}
};
println!("Resultado: {}", resultado);
}
O while executa enquanto uma condição é verdadeira. É ideal para cenários onde você precisa verificar uma condição antes de cada iteração. Diferente do loop, você não consegue retornar um valor diretamente do while.
fn main() {
let mut numero = 1;
while numero <= 5 {
println!("Número: {}", numero);
numero += 1;
}
// Exemplo prático: entrada do usuário
let mut tentativas = 0;
while tentativas < 3 {
println!("Tentativa {}", tentativas + 1);
tentativas += 1;
}
}
For: Iteração Segura e Idiomática
O for em Rust é muito diferente de linguagens como C. Ele itera sobre coleções (ranges, vetores, etc.) de forma segura, eliminando erros de índice. É a forma mais comum e recomendada de repetição quando você conhece antecipadamente sobre o que quer iterar.
fn main() {
// For com range
for i in 1..=5 {
println!("Número: {}", i);
}
// For com vetor
let numeros = vec![10, 20, 30, 40];
for num in numeros {
println!("Valor: {}", num);
}
// For com índice (não idiomático, evite)
let letras = vec!['a', 'b', 'c'];
for (indice, letra) in letras.iter().enumerate() {
println!("{}: {}", indice, letra);
}
// For com referência (quando não quer consumir)
let valores = vec![5, 10, 15];
for &valor in &valores {
println!("Valor: {}", valor);
}
}
Diferenças Entre Range e Iteradores
A notação 1..5 cria um range exclusivo (1 a 4), enquanto 1..=5 é inclusivo (1 a 5). Para vetores, use iter() para iteração por referência (mantém a posse do vetor) ou a iteração direta para consumir. A escolha entre loop, while e for deve se basear na clareza do código: use for quando possível, é mais seguro e idiomático em Rust.
fn main() {
// Consumindo vs referência
let dados = vec![1, 2, 3];
for x in &dados {
println!("{}", x);
}
println!("dados ainda está disponível: {:?}", dados);
// Break e continue funcionam em todos os loops
for i in 1..10 {
if i == 3 {
continue; // Pula para próxima iteração
}
if i == 8 {
break; // Sai do loop
}
println!("{}", i);
}
}
Conclusão
Dominando estruturas de controle em Rust, você domina a base da lógica programada. Três aprendizados principais: (1) use if como expressão para código mais conciso, e match para segurança em padrões complexos; (2) escolha loop para controle fino, while para condições dinâmicas e for para iterações sobre coleções; (3) lembre que em Rust, for é a escolha idiomática — segura contra erros de índice e mais legível. Pratique cada estrutura em pequenos programas para internalizar quando usar cada uma.