While em Rust
Um laço while continua rodando enquanto uma condição for true. Ele é a ferramenta certa quando você sabe o que está esperando, mesmo sem saber exatamente quantas vezes vai precisar repetir.
Laço while básico
Seção intitulada “Laço while básico”fn main() { let mut count = 1;
while count <= 5 { println!("{count}"); count += 1; }}Saída:
12345A condição (count <= 5) é verificada antes de cada volta do laço. Assim que ela fica false, o laço termina. Aqui, isso acontece quando count chega a 6.
while ou loop?
Seção intitulada “while ou loop?”Você poderia escrever a mesma coisa com loop e um if/break manual, mas o while diz o que você quer de forma mais direta: “continue enquanto isto for verdade”. Deixe o loop para os casos em que a condição de parada não se encaixa naturalmente no começo do laço.
// com while: claro e diretolet mut n = 0;while n < 3 { println!("{n}"); n += 1;}
// a mesma coisa com loop: funciona, mas tem mais para lerlet mut n = 0;loop { if n >= 3 { break; } println!("{n}"); n += 1;}Um exemplo mais realista
Seção intitulada “Um exemplo mais realista”O while é comum em situações como esperar um valor chegar a uma meta:
fn main() { let mut balance = 100;
while balance < 200 { balance += 25; println!("Saldo atual: {balance}"); }
println!("Meta atingida!");}Saída:
Saldo atual: 125Saldo atual: 150Saldo atual: 175Saldo atual: 200Meta atingida!A condição pode ser qualquer expressão que resulte em um bool, então você pode combinar verificações com && e ||, da página de Operadores, como em while balance < 200 && months < 12.
O Rust não tem do-while
Seção intitulada “O Rust não tem do-while”Algumas linguagens têm um laço do { ... } while (condição). Ele executa o corpo primeiro e só depois verifica a condição, então o corpo sempre roda pelo menos uma vez. O Rust não tem isso. Em vez disso, você usa loop e coloca a verificação no final.
Veja um caso em que isso importa. Para contar os dígitos de um número, você pode ir dividindo por 10 até não sobrar nada. Só que o número 0 também tem um dígito, e um while simples nunca roda para ele:
fn main() { let number = 0;
// O while verifica primeiro, então nunca roda para o 0. let mut n = number; let mut digits = 0; while n > 0 { digits += 1; n /= 10; } println!("segundo o while, {number} tem {digits} dígitos");
// loop + verificação no final executa o corpo pelo menos uma vez. let mut n = number; let mut digits = 0; loop { digits += 1; n /= 10; if n == 0 { break; } } println!("segundo o loop, {number} tem {digits} dígito");}Saída:
segundo o while, 0 tem 0 dígitossegundo o loop, 0 tem 1 dígitoTroque number por 4096 e as duas versões concordam: 4 dígitos. A diferença só aparece quando a condição já é falsa logo de início. Então a regra prática é: se o corpo precisa rodar pelo menos uma vez, escreva loop com o if ... { break; } no final.
Existe mais um tipo de laço while, o while let, que continua enquanto um valor combinar com um padrão. Ele é explicado na página If Let e While Let.
Prática
Seção intitulada “Prática”1. Some até passar de 100
Seção intitulada “1. Some até passar de 100”Some 1 + 2 + 3 + … e pare assim que o total for maior que 100. Imprima quantos números você somou e o total. Dica: você precisa de duas variáveis mut, uma para o próximo número e outra para o total.
Ver solução
fn main() { let mut next = 1; let mut total = 0;
while total <= 100 { total += next; next += 1; }
println!("Somei {} números, o total é {total}", next - 1);}Saída:
Somei 14 números, o total é 105Depois da última volta, next já avançou um passo, e é por isso que imprimimos next - 1. Vale a pena conferir esses detalhes de “um a mais, um a menos” com um exemplo pequeno de cabeça.
2. Divida pela metade até chegar a 1
Seção intitulada “2. Divida pela metade até chegar a 1”Comece com 1000. Enquanto o número for maior que 1, divida-o por 2 (divisão inteira) e imprima-o. No final, imprima quantas divisões foram necessárias. Dica: n /= 2 divide n por 2 e descarta o resto.
Ver solução
fn main() { let mut n = 1000; let mut steps = 0;
while n > 1 { n /= 2; steps += 1; println!("{n}"); }
println!("Foram necessárias {steps} divisões por 2 para chegar a 1");}Saída:
500250125623115731Foram necessárias 9 divisões por 2 para chegar a 1125 / 2 é 62, e não 62.5, porque os dois números são inteiros. É isso que faz o laço terminar exatamente no 1.
while condição { ... }repete enquanto a condição fortrue; ela é verificada antes de cada volta.- Garanta que alguma coisa dentro do laço acabe deixando a condição
false, ou ele vai rodar para sempre. - Prefira o
whileaoloopsempre que a condição de parada couber naturalmente em “enquanto X for verdade”. - O Rust não tem do-while. Quando o corpo precisa rodar pelo menos uma vez, use
loopcom a verificação dobreakno final.
Teste o que aprendeu
Seção intitulada “Teste o que aprendeu”Teste o que aprendeu
1. Qual é o erro clássico que causa um laço while infinito?
2. Segundo esta página, quando você deve preferir o while ao loop?
3. Como escrever um laço cujo corpo sempre roda pelo menos uma vez?
Pontuação: 0 / 3
Para saber mais
Seção intitulada “Para saber mais”- Conditional Loops with while — The Rust Book (em inglês): a introdução oficial, comparando o
whilecom oloop. - while — Rust by Example (em inglês): um FizzBuzz executável escrito com um laço
while. - Predicate loops — The Rust Reference (em inglês): as regras exatas de como um laço
whileé executado. - A palavra-chave
while— documentação da std (em inglês): um resumo curto dowhilee dowhile let, com exemplos.