@@ -4227,9 +4227,343 @@ Doing this is not particularly common, but every once in a while, it's useful.
42274227That's all you need to get the hang of closures! Closures are a little bit
42284228strange at first, but once you're used to using them, you'll miss them in any
42294229language that doesn't have them. Passing functions to other functions is
4230- incredibly powerful. Next, let's look at one of those things: iterators.
4230+ incredibly powerful. Next, let's look at one of those things: iterators.
42314231
4232- # iterators
4232+ # Iterators
4233+
4234+ Let's talk about loops.
4235+
4236+ Remember Rust's ` for ` loop? Here's an example:
4237+
4238+ ``` {rust}
4239+ for x in range(0i, 10i) {
4240+ println!("{:d}", x);
4241+ }
4242+ ```
4243+
4244+ Now that you know more Rust, we can talk in detail about how this works. The
4245+ ` range ` function returns an ** iterator** . An iterator is something that we can
4246+ call the ` .next() ` method on repeatedly, and it gives us a sequence of things.
4247+
4248+ Like this:
4249+
4250+ ``` {rust}
4251+ let mut range = range(0i, 10i);
4252+
4253+ loop {
4254+ match range.next() {
4255+ Some(x) => {
4256+ println!("{}", x);
4257+ }
4258+ None => { break }
4259+ }
4260+ }
4261+ ```
4262+
4263+ We make a mutable binding to the return value of ` range ` , which is our iterator.
4264+ We then ` loop ` , with an inner ` match ` . This ` match ` is used on the result of
4265+ ` range.next() ` , which gives us a reference to the next value of the iterator.
4266+ ` next ` returns an ` Option<int> ` , in this case, which will be ` Some(int) ` when
4267+ we have a value and ` None ` once we run out. If we get ` Some(int) ` , we print it
4268+ out, and if we get ` None ` , we ` break ` out of the loop.
4269+
4270+ This code sample is basically the same as our ` for ` loop version. The ` for `
4271+ loop is just a handy way to write this ` loop ` /` match ` /` break ` construct.
4272+
4273+ ` for ` loops aren't the only thing that uses iterators, however. Writing your
4274+ own iterator involves implementing the ` Iterator ` trait. While doing that is
4275+ outside of the scope of this guide, Rust provides a number of useful iterators
4276+ to accomplish various tasks. Before we talk about those, we should talk about a
4277+ Rust anti-pattern. And that's ` range ` .
4278+
4279+ Yes, we just talked about how ` range ` is cool. But ` range ` is also very
4280+ primitive. For example, if you needed to iterate over the contents of
4281+ a vector, you may be tempted to write this:
4282+
4283+ ``` {rust}
4284+ let nums = vec![1i, 2i, 3i];
4285+
4286+ for i in range(0u, nums.len()) {
4287+ println!("{}", nums[i]);
4288+ }
4289+ ```
4290+
4291+ This is strictly worse than using an actual iterator. The ` .iter() ` method on
4292+ vectors returns an iterator which iterates through a reference to each element
4293+ of the vector in turn. So write this:
4294+
4295+ ``` {rust}
4296+ let nums = vec![1i, 2i, 3i];
4297+
4298+ for num in nums.iter() {
4299+ println!("{}", num);
4300+ }
4301+ ```
4302+
4303+ There are two reasons for this. First, this is more semantic. We iterate
4304+ through the entire vector, rather than iterating through indexes, and then
4305+ indexing the vector. Second, this version is more efficient: the first version
4306+ will have extra bounds checking because it used indexing, ` nums[i] ` . But since
4307+ we yield a reference to each element of the vector in turn with the iterator,
4308+ there's no bounds checking in the second example. This is very common with
4309+ iterators: we can ignore unnecessary bounds checks, but still know that we're
4310+ safe.
4311+
4312+ There's another detail here that's not 100% clear because of how ` println! `
4313+ works. ` num ` is actually of type ` &int ` , that is, it's a reference to an ` int ` ,
4314+ not an ` int ` itself. ` println! ` handles the dereferencing for us, so we don't
4315+ see it. This code works fine too:
4316+
4317+ ``` {rust}
4318+ let nums = vec![1i, 2i, 3i];
4319+
4320+ for num in nums.iter() {
4321+ println!("{}", *num);
4322+ }
4323+ ```
4324+
4325+ Now we're explicitly dereferencing ` num ` . Why does ` iter() ` give us references?
4326+ Well, if it gave us the data itself, we would have to be its owner, which would
4327+ involve making a copy of the data and giving us the copy. With references,
4328+ we're just borrowing a reference to the data, and so it's just passing
4329+ a reference, without needing to do the copy.
4330+
4331+ So, now that we've established that ` range ` is often not what you want, let's
4332+ talk about what you do want instead.
4333+
4334+ There are three broad classes of things that are relevant here: iterators,
4335+ ** iterator adapters** , and ** consumers** . Here's some definitions:
4336+
4337+ * 'iterators' give you a sequence of values.
4338+ * 'iterator adapters' operate on an iterator, producing a new iterator with a
4339+ different output sequence.
4340+ * 'consumers' operate on an iterator, producing some final set of values.
4341+
4342+ Let's talk about consumers first, since you've already seen an iterator,
4343+ ` range ` .
4344+
4345+ ## Consumers
4346+
4347+ A 'consumer' operates on an iterator, returning some kind of value or values.
4348+ The most common consumer is ` collect() ` . This code doesn't quite compile,
4349+ but it shows the intention:
4350+
4351+ ``` {rust,ignore}
4352+ let one_to_one_hundred = range(0i, 100i).collect();
4353+ ```
4354+
4355+ As you can see, we call ` collect() ` on our iterator. ` collect() ` takes
4356+ as many values as the iterator will give it, and returns a collection
4357+ of the results. So why won't this compile? Rust can't determine what
4358+ type of things you want to collect, and so you need to let it know.
4359+ Here's the version that does compile:
4360+
4361+ ``` {rust}
4362+ let one_to_one_hundred = range(0i, 100i).collect::<Vec<int>>();
4363+ ```
4364+
4365+ If you remember, the ` ::<> ` syntax allows us to give a type hint,
4366+ and so we tell it that we want a vector of integers.
4367+
4368+ ` collect() ` is the most common consumer, but there are others too. ` find() `
4369+ is one:
4370+
4371+ ``` {rust}
4372+ let one_to_one_hundred = range(0i, 100i);
4373+
4374+ let greater_than_forty_two = range(0i, 100i)
4375+ .find(|x| *x >= 42);
4376+
4377+ match greater_than_forty_two {
4378+ Some(_) => println!("We got some numbers!"),
4379+ None => println!("No numbers found :("),
4380+ }
4381+ ```
4382+
4383+ ` find ` takes a closure, and works on a reference to each element of an
4384+ iterator. This closure returns ` true ` if the element is the element we're
4385+ looking for, and ` false ` otherwise. Because we might not find a matching
4386+ element, ` find ` returns an ` Option ` rather than the element itself.
4387+
4388+ Another important consumer is ` fold ` . Here's what it looks like:
4389+
4390+ ``` {rust}
4391+ let sum = range(1i, 100i)
4392+ .fold(0i, |sum, x| sum + x);
4393+ ```
4394+
4395+ ` fold() ` is a consumer that looks like this:
4396+ ` fold(base, |accumulator, element| ...) ` . It takes two arguments: the first
4397+ is an element called the "base". The second is a closure that itself takes two
4398+ arguments: the first is called the "accumulator," and the second is an
4399+ "element." Upon each iteration, the closure is called, and the result is the
4400+ value of the accumulator on the next iteration. On the first iteration, the
4401+ base is the value of the accumulator.
4402+
4403+ Okay, that's a bit confusing. Let's examine the values of all of these things
4404+ in this iterator:
4405+
4406+ | base | accumulator | element | closure result |
4407+ | ------| -------------| ---------| ----------------|
4408+ | 0i | 0i | 1i | 1i |
4409+ | 0i | 1i | 2i | 3i |
4410+ | 0i | 3i | 3i | 6i |
4411+
4412+ We called ` fold() ` with these arguments:
4413+
4414+ ``` {rust}
4415+ # range(1i, 5i)
4416+ .fold(0i, |sum, x| sum + x);
4417+ ```
4418+
4419+ So, ` 0i ` is our base, ` sum ` is our accumulator, and ` x ` is our element. On the
4420+ first iteration, we set ` sum ` to ` 0i ` , and ` x ` is the first element of ` nums ` ,
4421+ ` 1i ` . We then add ` sum ` and ` x ` , which gives us ` 0i + 1i = 1i ` . On the second
4422+ iteration, that value becomes our accumulator, ` sum ` , and the element is
4423+ the second element of the array, ` 2i ` . ` 1i + 2i = 3i ` , and so that becomes
4424+ the value of the accumulator for the last iteration. On that iteration,
4425+ ` x ` is the last element, ` 3i ` , and ` 3i + 3i = 6i ` , which is our final
4426+ result for our sum. ` 1 + 2 + 3 = 6 ` , and that's the result we got.
4427+
4428+ Whew. ` fold ` can be a bit strange the first few times you see it, but once it
4429+ clicks, you can use it all over the place. Any time you have a list of things,
4430+ and you want a single result, ` fold ` is appropriate.
4431+
4432+ Consumers are important due to one additional property of iterators we haven't
4433+ talked about yet: laziness. Let's talk some more about iterators, and you'll
4434+ see why consumers matter.
4435+
4436+ ## Iterators
4437+
4438+ As we've said before, an iterator is something that we can call the ` .next() `
4439+ method on repeatedly, and it gives us a sequence of things. Because you need
4440+ to call the method, this means that iterators are ** lazy** . This code, for
4441+ example, does not actually generate the numbers ` 1-100 ` , and just creates a
4442+ value that represents the sequence:
4443+
4444+ ``` {rust}
4445+ let nums = range(1i, 100i);
4446+ ```
4447+
4448+ Since we didn't do anything with the range, it didn't generate the sequence.
4449+ Once we add the consumer:
4450+
4451+ ``` {rust}
4452+ let nums = range(1i, 100i).collect::<Vec<int>>();
4453+ ```
4454+
4455+ Now, ` collect() ` will require that ` range() ` give it some numbers, and so
4456+ it will do the work of generating the sequence.
4457+
4458+ ` range ` is one of two basic iterators that you'll see. The other is ` iter() ` ,
4459+ which you've used before. ` iter() ` can turn a vector into a simple iterator
4460+ that gives you each element in turn:
4461+
4462+ ``` {rust}
4463+ let nums = [1i, 2i, 3i];
4464+
4465+ for num in nums.iter() {
4466+ println!("{}", num);
4467+ }
4468+ ```
4469+
4470+ These two basic iterators should serve you well. There are some more
4471+ advanced iterators, including ones that are infinite. Like ` count ` :
4472+
4473+ ``` {rust}
4474+ std::iter::count(1i, 5i);
4475+ ```
4476+
4477+ This iterator counts up from one, adding five each time. It will give
4478+ you a new integer every time, forever. Well, technically, until the
4479+ maximum number that an ` int ` can represent. But since iterators are lazy,
4480+ that's okay! You probably don't want to use ` collect() ` on it, though...
4481+
4482+ That's enough about iterators. Iterator adapters are the last concept
4483+ we need to talk about with regards to iterators. Let's get to it!
4484+
4485+ ## Iterator adapters
4486+
4487+ "Iterator adapters" take an iterator and modify it somehow, producing
4488+ a new iterator. The simplest one is called ` map ` :
4489+
4490+ ``` {rust,ignore}
4491+ range(1i, 100i).map(|x| x + 1i);
4492+ ```
4493+
4494+ ` map ` is called upon another iterator, and produces a new iterator where each
4495+ element reference has the closure it's been given as an argument called on it.
4496+ So this would give us the numbers from ` 2-101 ` . Well, almost! If you
4497+ compile the example, you'll get a warning:
4498+
4499+ ``` {notrust,ignore}
4500+ 2:37 warning: unused result which must be used: iterator adaptors are lazy and
4501+ do nothing unless consumed, #[warn(unused_must_use)] on by default
4502+ range(1i, 100i).map(|x| x + 1i);
4503+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4504+ ```
4505+
4506+ Laziness strikes again! That closure will never execute. This example
4507+ doesn't print any numbers:
4508+
4509+ ``` {rust,ignore}
4510+ range(1i, 100i).map(|x| println!("{}", x));
4511+ ```
4512+
4513+ If you are trying to execute a closure on an iterator for its side effects,
4514+ just use ` for ` instead.
4515+
4516+ There are tons of interesting iterator adapters. ` take(n) ` will get the
4517+ first ` n ` items out of an iterator, and return them as a list. Let's
4518+ try it out with our infinite iterator from before, ` count() ` :
4519+
4520+ ``` {rust}
4521+ for i in std::iter::count(1i, 5i).take(5) {
4522+ println!("{}", i);
4523+ }
4524+ ```
4525+
4526+ This will print
4527+
4528+ ``` {notrust,ignore}
4529+ 1
4530+ 6
4531+ 11
4532+ 16
4533+ 21
4534+ ```
4535+
4536+ ` filter() ` is an adapter that takes a closure as an argument. This closure
4537+ returns ` true ` or ` false ` . The new iterator ` filter() ` produces returns
4538+ only the elements that that closure returned ` true ` for:
4539+
4540+ ``` {rust}
4541+ for i in range(1i, 100i).filter(|x| x % 2 == 0) {
4542+ println!("{}", i);
4543+ }
4544+ ```
4545+
4546+ This will print all of the even numbers between one and a hundred.
4547+
4548+ You can chain all three things together: start with an iterator, adapt it
4549+ a few times, and then consume the result. Check it out:
4550+
4551+ ``` {rust}
4552+ range(1i, 1000i)
4553+ .filter(|x| x % 2 == 0)
4554+ .filter(|x| x % 3 == 0)
4555+ .take(5)
4556+ .collect::<Vec<int>>();
4557+ ```
4558+
4559+ This will give you a vector containing ` 6 ` , ` 12 ` , ` 18 ` , ` 24 ` , and ` 30 ` .
4560+
4561+ This is just a small taste of what iterators, iterator adapters, and consumers
4562+ can help you with. There are a number of really useful iterators, and you can
4563+ write your own as well. Iterators provide a safe, efficient way to manipulate
4564+ all kinds of lists. They're a little unusual at first, but if you play with
4565+ them, you'll get hooked. For a full list of the different iterators and
4566+ consumers, check out the [ iterator module documentation] ( std/iter/index.html ) .
42334567
42344568# Generics
42354569
0 commit comments