<buttonid="sidebar-toggle"class="icon-button"type="button"title="Toggle Table of Contents"aria-label="Toggle Table of Contents"aria-controls="sidebar">
<ahref="print.html"title="Print this book"aria-label="Print this book">
<iid="print-button"class="fa fa-print"></i>
</a>
</div>
</div>
<divid="search-wrapper"class="hidden">
<formid="searchbar-outer"class="searchbar-outer">
<inputtype="search"name="search"id="searchbar"name="searchbar"placeholder="Search this book ..."aria-controls="searchresults-outer"aria-describedby="searchresults-header">
<p>An iterator is a construct that can give you the items in the collection, one at a time. Actually, we have already used iterators a lot: the <code>for</code> loop gives you an iterator. When you want to use an iterator other times, you have to choose what kind:</p>
<ul>
<li><code>.iter()</code> for an iterator of references</li>
<li><code>.iter_mut()</code> for an iterator of mutable references</li>
<li><code>.into_iter()</code> for an iterator of values (not references)</li>
<p>A <code>for</code> loop is actually just an iterator that owns its values. That's why it can make it mutable and then you can change the values when you use it.</p>
let vector1 = vec![1, 2, 3]; // we will use .iter() and .into_iter() on this one
let vector1_a = vector1.iter().map(|x| x + 1).collect::<Vec<i32>>();
let vector1_b = vector1.into_iter().map(|x| x * 10).collect::<Vec<i32>>();
let mut vector2 = vec![10, 20, 30]; // we will use .iter_mut() on this one
vector2.iter_mut().for_each(|x| *x +=100);
println!("{:?}", vector1_a);
println!("{:?}", vector2);
println!("{:?}", vector1_b);
}
</code></pre></pre>
<p>This prints:</p>
<pre><codeclass="language-text">[2, 3, 4]
[110, 120, 130]
[10, 20, 30]
</code></pre>
<p>The first two we used a method called <code>.map()</code>. This method lets you do something to every item, then pass it on. The last one we used is one called <code>.for_each()</code>. This method just lets you do something to every item. <code>.iter_mut()</code> plus <code>for_each()</code> is basically just a <code>for</code> loop. Inside each method we can give a name to every item (we just called it <code>x</code>) and use that to change it. These are called closures and we will learn about them in the next section.</p>
<p>Let's go over them again, one at a time.</p>
<p>First we used <code>.iter()</code> on <code>vector1</code> to get references. We added 1 to each, and made it into a new Vec. <code>vector1</code> is still alive because we only used references: we didn't take by value. Now we have <code>vector1</code>, and a new Vec called <code>vector1_a</code>. Because <code>.map()</code> just passes it on, we needed to use <code>.collect()</code> to make it into a <code>Vec</code>.</p>
<p>Then we used <code>into_iter</code> to get an iterator by value from <code>vector1</code>. This destroys <code>vector1</code>, because that's what <code>into_iter()</code> does. So after we make <code>vector1_b</code> we can't use <code>vector1</code> again.</p>
<p>Finally we used <code>.iter_mut()</code> for <code>vector2</code>. It is mutable, so we don't need to use <code>.collect()</code> to create a new Vec. Instead, we change the values in the same Vec with mutable references. So <code>vector2</code> is still there. Because we don't need a new Vec, we use <code>for_each</code>: it's just like a <code>for</code> loop.</p>
<p>An iterator works by using a method called <code>.next()</code>, which gives an <code>Option</code>. When you use an iterator, Rust calls <code>next()</code> over and over again. If it gets <code>Some</code>, it keeps going. If it gets <code>None</code>, it stops.</p>
<p>Do you remember the <code>assert_eq!</code> macro? In documentation, you see it all the time. Here it is showing how an iterator works.</p>
let my_vec = vec!['a', 'b', '거', '柳']; // Just a regular Vec
let mut my_vec_iter = my_vec.iter(); // This is an Iterator type now, but we haven't called it yet
assert_eq!(my_vec_iter.next(), Some(&'a')); // Call the first item with .next()
assert_eq!(my_vec_iter.next(), Some(&'b')); // Call the next
assert_eq!(my_vec_iter.next(), Some(&'거')); // Again
assert_eq!(my_vec_iter.next(), Some(&'柳')); // Again
assert_eq!(my_vec_iter.next(), None); // Nothing is left: just None
assert_eq!(my_vec_iter.next(), None); // You can keep calling .next() but it will always be None
}
</code></pre></pre>
<p>Implementing <code>Iterator</code> for your own struct or enum is not too hard. First let's make a book library and think about it.</p>
<pre><preclass="playground"><codeclass="language-rust">#[derive(Debug)] // we want to print it with {:?}
struct Library {
library_type: LibraryType, // this is our enum
books: Vec<String>, // list of books
}
#[derive(Debug)]
enum LibraryType { // libraries can be city libraries or country libraries
City,
Country,
}
impl Library {
fn add_book(&mut self, book: &str) { // we use add_book to add new books
self.books.push(book.to_string()); // we take a &str and turn it into a String, then add it to the Vec
}
fn new() -> Self { // this creates a new Library
Self {
library_type: LibraryType::City, // most are in the city so we'll choose City
// most of the time
books: Vec::new(),
}
}
}
fn main() {
let mut my_library = Library::new(); // make a new library
my_library.add_book("The Doom of the Darksword"); // add some books
my_library.add_book("Demian - die Geschichte einer Jugend");
my_library.add_book("구운몽");
my_library.add_book("吾輩は猫である");
println!("{:?}", my_library.books); // we can print our list of books
}
</code></pre></pre>
<p>That works well. Now we want to implement <code>Iterator</code> for the library so we can use it in a <code>for</code> loop. Right now if we try a <code>for</code> loop, it doesn't work:</p>
<pre><codeclass="language-text">error[E0277]: `Library` is not an iterator
--> src\main.rs:47:16
|
47 | for item in my_library {
| ^^^^^^^^^^ `Library` is not an iterator
|
= help: the trait `std::iter::Iterator` is not implemented for `Library`
= note: required by `std::iter::IntoIterator::into_iter`
</code></pre>
<p>But we can make library into an iterator with <code>impl Iterator for Library</code>. Information on the <code>Iterator</code> trait is here in the standard library: <ahref="https://doc.rust-lang.org/std/iter/trait.Iterator.html">https://doc.rust-lang.org/std/iter/trait.Iterator.html</a></p>
<p>On the top left of the page it says: <code>Associated Types: Item</code> and <code>Required Methods: next</code>. An "associated type" means "a type that goes together". Our associated type will be <code>String</code>, because we want the iterator to give us Strings.</p>
<p>In the page it has an example that looks like this:</p>
<pre><preclass="playground"><codeclass="language-rust">// an iterator which alternates between Some and None
struct Alternate {
state: i32,
}
impl Iterator for Alternate {
type Item = i32;
fn next(&mut self) -> Option<i32> {
let val = self.state;
self.state = self.state + 1;
// if it's even, Some(i32), else None
if val % 2 == 0 {
Some(val)
} else {
None
}
}
}
fn main() {}
</code></pre></pre>
<p>You can see that under <code>impl Iterator for Alternate</code> it says <code>type Item = i32</code>. This is the associated type. Our iterator will be for our list of books, which is a <code>Vec<String></code>. When we call next, it will give us a <code>String</code>. So we will write <code>type Item = String;</code>. That is the associated item.</p>
<p>To implement <code>Iterator</code>, you need to write the <code>fn next()</code> function. This is where you decide what the iterator should do. For our <code>Library</code>, we want it to give us the last books first. So we will <code>match</code> with <code>.pop()</code> which takes the last item off if it is <code>Some</code>. We also want to print " is found!" for each item. Now it looks like this:</p>