Introdução
Neste laboratório, aprendemos sobre o uso de loops for e ranges em Rust. Podemos usar o loop for juntamente com a notação de range a..b para iterar através de um intervalo de valores. Por exemplo, podemos escrever o programa FizzBuzz usando um loop for em vez de um loop while. Além disso, podemos usar a notação ..= para um intervalo inclusivo em ambas as extremidades. O loop for também pode interagir com iteradores de diferentes maneiras, como usar iter para emprestar cada elemento de uma coleção, into_iter para consumir a coleção ou iter_mut para emprestar mutávelmente cada elemento da coleção. Cada um desses métodos fornece uma visão diferente dos dados dentro da coleção, permitindo que diferentes ações sejam executadas.
Nota: Se o laboratório não especificar um nome de arquivo, você pode usar qualquer nome de arquivo que desejar. Por exemplo, você pode usar
main.rs, compilar e executá-lo comrustc main.rs && ./main.
Loops for
for e range
A construção for in pode ser usada para iterar através de um Iterator. Uma das maneiras mais fáceis de criar um iterador é usar a notação de intervalo a..b. Isso gera valores de a (inclusivo) a b (exclusivo) em incrementos de um.
Vamos escrever FizzBuzz usando for em vez de while.
fn main() {
// `n` assumirá os valores: 1, 2, ..., 100 em cada iteração
for n in 1..101 {
if n % 15 == 0 {
println!("fizzbuzz");
} else if n % 3 == 0 {
println!("fizz");
} else if n % 5 == 0 {
println!("buzz");
} else {
println!("{}", n);
}
}
}
Alternativamente, a..=b pode ser usado para um intervalo inclusivo em ambas as extremidades. O código acima pode ser reescrito como:
fn main() {
// `n` assumirá os valores: 1, 2, ..., 100 em cada iteração
for n in 1..=100 {
if n % 15 == 0 {
println!("fizzbuzz");
} else if n % 3 == 0 {
println!("fizz");
} else if n % 5 == 0 {
println!("buzz");
} else {
println!("{}", n);
}
}
}
for e iteradores
A construção for in é capaz de interagir com um Iterator de várias maneiras. Como discutido na seção sobre o trait Iterator, por padrão, o loop for aplicará a função into_iter à coleção. No entanto, este não é o único meio de converter coleções em iteradores.
into_iter, iter e iter_mut lidam com a conversão de uma coleção em um iterador de maneiras diferentes, fornecendo diferentes visões dos dados dentro dela.
iter- Este método empresta cada elemento da coleção em cada iteração. Assim, deixando a coleção intacta e disponível para reutilização após o loop.
fn main() {
let names = vec!["Bob", "Frank", "Ferris"];
for name in names.iter() {
match name {
&"Ferris" => println!("Há um rustacean entre nós!"),
// TODO ^ Tente remover o & e corresponder apenas a "Ferris"
_ => println!("Olá {}", name),
}
}
println!("names: {:?}", names);
}
into_iter- Este método consome a coleção para que, em cada iteração, os dados exatos sejam fornecidos. Uma vez que a coleção foi consumida, ela não está mais disponível para reutilização, pois foi 'movida' dentro do loop.
fn main() {
let names = vec!["Bob", "Frank", "Ferris"];
for name in names.into_iter() {
match name {
"Ferris" => println!("Há um rustacean entre nós!"),
_ => println!("Olá {}", name),
}
}
println!("names: {:?}", names);
// FIXME ^ Comente esta linha
}
iter_mut- Este método empresta mutávelmente cada elemento da coleção, permitindo que a coleção seja modificada no local.
fn main() {
let mut names = vec!["Bob", "Frank", "Ferris"];
for name in names.iter_mut() {
*name = match name {
&mut "Ferris" => "Há um rustacean entre nós!",
_ => "Olá",
}
}
println!("names: {:?}", names);
}
Nos trechos acima, observe o tipo do ramo match, que é a principal diferença nos tipos de iteração. A diferença no tipo, é claro, implica ações diferentes que podem ser executadas.
Resumo
Parabéns! Você concluiu o laboratório de Loops for. Você pode praticar mais laboratórios no LabEx para aprimorar suas habilidades.