Iterators
One of the great things about being a Perl programmer is that we get to read Higher-Order Perl. And one of the great things about Higher-Order Perl is the explanation of iterators.
Rust iterators are a joy to use. They really make Rust fun. If you think a "low-level" systems language is going to be tedious to use, you're in for a treat. If you like to use things like map
and grep
in Perl, you're going to love Rust.
For loops
Earlier, I mentioned revisiting Rust's for loop. Let's do that now. It looks like this
fn main() { let names = vec!["Hank", "Dean", "Brock"]; for name in names { println!("Hello, {}!", name); } }
But this is really syntactic sugar for something like this
fn main() { let names = vec!["Hank", "Dean", "Brock"]; let mut iterator = names.into_iter(); while let Some(name) = iterator.next() { println!("Hello, {}!", name); } }
That is, Rust for
loops are not really a separate thing. They are just an alternate syntax for consuming iterators.
Rust has an Iterator trait that we can use to define our own iterators. Then we can use for
loops on them.
Lazy
Rust iterators are lazy. That means they must be consumed before they do anything. If we write this
fn main() { let names = vec!["Hank", "Dean", "Brock"]; let hellos = names.iter().map(|name| format!("Hello, {}!", name)); println!("{:#?}", hellos); }
then nothing happens. We've set the machine up, but we haven't turned the crank. We have to do something like collect
it into a vector to do that.
fn main() { let names = vec!["Hank", "Dean", "Brock"]; let hellos = names.iter().map(|name| format!("Hello, {}!", name)).collect::<Vec<_>>(); println!("{:#?}", hellos); }
Being lazy also means that iterators can be infinite.