I might butcher this explanation... but very loosely speaking: An iterator adapter is something that takes an iterator as an input, and changes that iterator in some way. Let's use (1..=10)
as our iterator for the example.
for i in 1..=10 {
println!("{}", i);
}
will just print the numbers 1 through to 10. But let's say we only wanted to print the even numbers. We could do
for i in 1..=10 {
if i % 2 == 0 {
println!("{}", i);
}
}
to do nothing for the iterations where i
is odd. Or, we could filter out the iterations where i
is odd:
for i in (1..=10).filter(|x| x % 2 == 0) {
println!("{}", i);
}
The .filter()
call here is an iterator adapter that takes (1..=10)
as an input, and returns a new iterator that skips the odd numbers. You can often use multiple iterator adapters together. This one will square the even numbers from 1 to 10. The .map()
is an iterator adapter:
for i in (1..=10).filter(|x| x % 2 == 0).map(|x| x * x) {
println!("{}", i);
}
And here's one that uses the .sum()
adaptor:
let sum: i32 = (1..=10).filter(|x| x % 2 == 0).map(|x| x * x).sum();
println!("{}", sum);
The sum iterator adaptor takes an iterator as an input and uses it to calculate and return a sum, but doesn't return another iterator.
Same case with for_each
except that for_each
doesn't return anything.