For em Rust
O for percorre um intervalo ou uma coleção, um item de cada vez. Dos três tipos de laço do Rust, este é o que você vai usar mais.
Percorrendo um intervalo
Seção intitulada “Percorrendo um intervalo”fn main() { for i in 1..=5 { println!("{i}"); }}Saída:
123451..=5 é um intervalo (range) que inclui as duas pontas (de 1 a 5). Se você tirar o = e escrever 1..5, ele para um número antes, e você fica com 1 a 4. É fácil tropeçar nessa diferença de um, então vale conferir qual dos dois você quis usar.
Percorrendo uma coleção
Seção intitulada “Percorrendo uma coleção”É aqui que o for brilha de verdade: percorrer um array ou um vetor sem precisar controlar um índice por conta própria:
fn main() { let fruits = ["maçã", "banana", "cereja"];
for fruit in fruits { println!("{fruit}"); }}Saída:
maçãbananacerejaCompare isso com contar na mão usando um while e acessar pelo índice (fruits[i]): fica mais curto e não existe índice para errar. Você vai aprender mais sobre arrays e vetores nas páginas de Arrays e Vetores.
Pegando o índice também, com .enumerate()
Seção intitulada “Pegando o índice também, com .enumerate()”Se você precisa da posição e do valor ao mesmo tempo, use .enumerate():
fn main() { let fruits = ["maçã", "banana", "cereja"];
for (index, fruit) in fruits.iter().enumerate() { println!("{index}: {fruit}"); }}Saída:
0: maçã1: banana2: cerejaA parte (index, fruit) é um padrão de tupla: a cada volta você recebe um par, e o laço o separa em duas variáveis para você.
Contando de trás para frente e de tantos em tantos
Seção intitulada “Contando de trás para frente e de tantos em tantos”E se você quiser contar de 3 para baixo, ou passar só por um número sim, outro não? Uma primeira tentativa natural é um intervalo ao contrário, como 3..=1. Ele compila, mas o laço nunca roda. Um intervalo só conta para cima, então um intervalo cujo início é maior que o fim está simplesmente vazio.
Em vez disso, use um intervalo normal e mude o jeito de percorrê-lo:
.rev()percorre o intervalo ao contrário..step_by(n)pega um valor a cadan, começando pelo primeiro.
fn main() { for i in (1..=3).rev() { println!("{i}..."); } println!("Já!");
for even in (0..=10).step_by(2) { print!("{even} "); } println!();
for i in 3..=1 { println!("isto nunca aparece: {i}"); }}Saída:
3...2...1...Já!0 2 4 6 8 10Repare nos parênteses: (1..=3).rev(). Sem eles, o Rust leria 1..=3.rev() como “de 1 até 3.rev()”, que não é o que você quer. Você também pode combinar os dois: (0..=10).rev().step_by(5) dá 10, 5, 0.
Por que preferir o for ao while para contar
Seção intitulada “Por que preferir o for ao while para contar”Você poderia escrever um laço de contagem com while, mas o for com um intervalo elimina toda uma categoria de erros: não existe contador manual para esquecer de atualizar nem risco de passar uma posição além do fim de um array. Quem programa em Rust usa o for por padrão e só recorre ao while quando não há um intervalo ou uma coleção natural para percorrer.
Prática
Seção intitulada “Prática”1. Uma tabuada
Seção intitulada “1. Uma tabuada”Imprima a tabuada do 7, de 7 x 1 = 7 até 7 x 10 = 70. Dica: um único laço for sobre 1..=10 basta. Você pode fazer a multiplicação direto dentro do println!.
Ver solução
fn main() { for i in 1..=10 { println!("7 x {i} = {}", 7 * i); }}Saída:
7 x 1 = 77 x 2 = 147 x 3 = 217 x 4 = 287 x 5 = 357 x 6 = 427 x 7 = 497 x 8 = 567 x 9 = 637 x 10 = 70Variáveis com nome, como {i}, podem ir direto dentro das chaves. Um cálculo como 7 * i não pode, então ele usa um {} vazio com o valor depois da vírgula.
2. Some os números ímpares
Seção intitulada “2. Some os números ímpares”Some todos os números ímpares de 1 a 99 e imprima o total. Dica: (1..100).step_by(2) dá 1, 3, 5, … 99. Mantenha um total mut fora do laço.
Ver solução
fn main() { let mut total = 0;
for n in (1..100).step_by(2) { total += n; }
println!("A soma dos ímpares de 1 a 99 é {total}");}Saída:
A soma dos ímpares de 1 a 99 é 2500Outro jeito é percorrer 1..100 e só somar n quando n % 2 == 1. Os dois funcionam. O step_by só pula os números pares em vez de verificar cada um.
for item in intervalo_ou_coleção { ... }é o laço do dia a dia em Rust.1..=5inclui as duas pontas;1..5para um número antes do 5.- Percorra arrays e vetores diretamente para pegar cada valor sem acessar índices na mão.
- Use
.enumerate()quando precisar do índice junto com o valor. - Um intervalo ao contrário, como
3..=1, está vazio. Use(1..=3).rev()para contar para baixo e.step_by(n)para pular valores.
Teste o que aprendeu
Seção intitulada “Teste o que aprendeu”Teste o que aprendeu
1. Qual é a diferença entre 1..=5 e 1..5 em um laço for?
2. Como obter o índice e o valor ao mesmo tempo ao percorrer uma coleção?
3. Por que o for costuma ser preferido ao while para percorrer uma coleção?
4. O que for i in 5..=1 { ... } faz?
Pontuação: 0 / 4
Para saber mais
Seção intitulada “Para saber mais”- Looping Through a Collection with for — The Rust Book (em inglês): a introdução oficial, incluindo uma contagem regressiva com
.rev(). - for and range — Rust by Example (em inglês): exemplos executáveis de intervalos, além de
iter,iter_muteinto_iterpara coleções. - Iterator loops — The Rust Reference (em inglês): as regras exatas do que um laço
forfaz por baixo dos panos. Iterator::step_by— documentação da std (em inglês): como ostep_byfunciona, com exemplos. Orevestá documentado na mesma página.