@@ -4049,9 +4049,343 @@ Doing this is not particularly common, but every once in a while, it's useful.
40494049That's all you need to get the hang of closures! Closures are a little bit
40504050strange at first, but once you're used to using them, you'll miss them in any
40514051language that doesn't have them. Passing functions to other functions is
4052- incredibly powerful. Next, let's look at one of those things: iterators.
4052+ incredibly powerful. Next, let's look at one of those things: iterators.
40534053
4054- # iterators
4054+ # Iterators
4055+
4056+ Let's talk about loops.
4057+
4058+ Remember Rust's ` for ` loop? Here's an example:
4059+
4060+ ``` {rust}
4061+ for x in range(0i, 10i) {
4062+ println!("{:d}", x);
4063+ }
4064+ ```
4065+
4066+ Now that you know more Rust, we can talk in detail about how this works. The
4067+ ` range ` function returns an ** iterator** . An iterator is something that we can
4068+ call the ` .next() ` method on repeatedly, and it gives us a sequence of things.
4069+
4070+ Like this:
4071+
4072+ ``` {rust}
4073+ let mut range = range(0i, 10i);
4074+
4075+ loop {
4076+ match range.next() {
4077+ Some(x) => {
4078+ println!("{}", x);
4079+ }
4080+ None => { break }
4081+ }
4082+ }
4083+ ```
4084+
4085+ We make a mutable binding to the return value of ` range ` , which is our iterator.
4086+ We then ` loop ` , with an inner ` match ` . This ` match ` is used on the result of
4087+ ` range.next() ` , which gives us a reference to the next value of the iterator.
4088+ ` next ` returns an ` Option<int> ` , in this case, which will be ` Some(int) ` when
4089+ we have a value and ` None ` once we run out. If we get ` Some(int) ` , we print it
4090+ out, and if we get ` None ` , we ` break ` out of the loop.
4091+
4092+ This code sample is basically the same as our ` for ` loop version. The ` for `
4093+ loop is just a handy way to write this ` loop ` /` match ` /` break ` construct.
4094+
4095+ ` for ` loops aren't the only thing that uses iterators, however. Writing your
4096+ own iterator involves implementing the ` Iterator ` trait. While doing that is
4097+ outside of the scope of this guide, Rust provides a number of useful iterators
4098+ to accomplish various tasks. Before we talk about those, we should talk about a
4099+ Rust anti-pattern. And that's ` range ` .
4100+
4101+ Yes, we just talked about how ` range ` is cool. But ` range ` is also very
4102+ primitive. For example, if you needed to iterate over the contents of
4103+ a vector, you may be tempted to write this:
4104+
4105+ ``` {rust}
4106+ let nums = vec![1i, 2i, 3i];
4107+
4108+ for i in range(0u, nums.len()) {
4109+ println!("{}", nums[i]);
4110+ }
4111+ ```
4112+
4113+ This is strictly worse than using an actual iterator. The ` .iter() ` method on
4114+ vectors returns an iterator which iterates through a reference to each element
4115+ of the vector in turn. So write this:
4116+
4117+ ``` {rust}
4118+ let nums = vec![1i, 2i, 3i];
4119+
4120+ for num in nums.iter() {
4121+ println!("{}", num);
4122+ }
4123+ ```
4124+
4125+ There are two reasons for this. First, this is more semantic. We iterate
4126+ through the entire vector, rather than iterating through indexes, and then
4127+ indexing the vector. Second, this version is more efficient: the first version
4128+ will have extra bounds checking because it used indexing, ` nums[i] ` . But since
4129+ we yield a reference to each element of the vector in turn with the iterator,
4130+ there's no bounds checking in the second example. This is very common with
4131+ iterators: we can ignore unnecessary bounds checks, but still know that we're
4132+ safe.
4133+
4134+ There's another detail here that's not 100% clear because of how ` println! `
4135+ works. ` num ` is actually of type ` &int ` , that is, it's a reference to an ` int ` ,
4136+ not an ` int ` itself. ` println! ` handles the dereferencing for us, so we don't
4137+ see it. This code works fine too:
4138+
4139+ ``` {rust}
4140+ let nums = vec![1i, 2i, 3i];
4141+
4142+ for num in nums.iter() {
4143+ println!("{}", *num);
4144+ }
4145+ ```
4146+
4147+ Now we're explicitly dereferencing ` num ` . Why does ` iter() ` give us references?
4148+ Well, if it gave us the data itself, we would have to be its owner, which would
4149+ involve making a copy of the data and giving us the copy. With references,
4150+ we're just borrowing a reference to the data, and so it's just passing
4151+ a reference, without needing to do the copy.
4152+
4153+ So, now that we've established that ` range ` is often not what you want, let's
4154+ talk about what you do want instead.
4155+
4156+ There are three broad classes of things that are relevant here: iterators,
4157+ ** iterator adapters** , and ** consumers** . Here's some definitions:
4158+
4159+ * 'iterators' give you a sequence of values.
4160+ * 'iterator adapters' operate on an iterator, producing a new iterator with a
4161+ different output sequence.
4162+ * 'consumers' operate on an iterator, producing some final set of values.
4163+
4164+ Let's talk about consumers first, since you've already seen an iterator,
4165+ ` range ` .
4166+
4167+ ## Consumers
4168+
4169+ A 'consumer' operates on an iterator, returning some kind of value or values.
4170+ The most common consumer is ` collect() ` . This code doesn't quite compile,
4171+ but it shows the intention:
4172+
4173+ ``` {rust,ignore}
4174+ let one_to_one_hundred = range(0i, 100i).collect();
4175+ ```
4176+
4177+ As you can see, we call ` collect() ` on our iterator. ` collect() ` takes
4178+ as many values as the iterator will give it, and returns a collection
4179+ of the results. So why won't this compile? Rust can't determine what
4180+ type of things you want to collect, and so you need to let it know.
4181+ Here's the version that does compile:
4182+
4183+ ``` {rust}
4184+ let one_to_one_hundred = range(0i, 100i).collect::<Vec<int>>();
4185+ ```
4186+
4187+ If you remember, the ` ::<> ` syntax allows us to give a type hint,
4188+ and so we tell it that we want a vector of integers.
4189+
4190+ ` collect() ` is the most common consumer, but there are others too. ` find() `
4191+ is one:
4192+
4193+ ``` {rust}
4194+ let one_to_one_hundred = range(0i, 100i);
4195+
4196+ let greater_than_forty_two = range(0i, 100i)
4197+ .find(|x| *x >= 42);
4198+
4199+ match greater_than_forty_two {
4200+ Some(_) => println!("We got some numbers!"),
4201+ None => println!("No numbers found :("),
4202+ }
4203+ ```
4204+
4205+ ` find ` takes a closure, and works on a reference to each element of an
4206+ iterator. This closure returns ` true ` if the element is the element we're
4207+ looking for, and ` false ` otherwise. Because we might not find a matching
4208+ element, ` find ` returns an ` Option ` rather than the element itself.
4209+
4210+ Another important consumer is ` fold ` . Here's what it looks like:
4211+
4212+ ``` {rust}
4213+ let sum = range(1i, 100i)
4214+ .fold(0i, |sum, x| sum + x);
4215+ ```
4216+
4217+ ` fold() ` is a consumer that looks like this:
4218+ ` fold(base, |accumulator, element| ...) ` . It takes two arguments: the first
4219+ is an element called the "base". The second is a closure that itself takes two
4220+ arguments: the first is called the "accumulator," and the second is an
4221+ "element." Upon each iteration, the closure is called, and the result is the
4222+ value of the accumulator on the next iteration. On the first iteration, the
4223+ base is the value of the accumulator.
4224+
4225+ Okay, that's a bit confusing. Let's examine the values of all of these things
4226+ in this iterator:
4227+
4228+ | base | accumulator | element | closure result |
4229+ | ------| -------------| ---------| ----------------|
4230+ | 0i | 0i | 1i | 1i |
4231+ | 0i | 1i | 2i | 3i |
4232+ | 0i | 3i | 3i | 6i |
4233+
4234+ We called ` fold() ` with these arguments:
4235+
4236+ ``` {rust}
4237+ # range(1i, 5i)
4238+ .fold(0i, |sum, x| sum + x);
4239+ ```
4240+
4241+ So, ` 0i ` is our base, ` sum ` is our accumulator, and ` x ` is our element. On the
4242+ first iteration, we set ` sum ` to ` 0i ` , and ` x ` is the first element of ` nums ` ,
4243+ ` 1i ` . We then add ` sum ` and ` x ` , which gives us ` 0i + 1i = 1i ` . On the second
4244+ iteration, that value becomes our accumulator, ` sum ` , and the element is
4245+ the second element of the array, ` 2i ` . ` 1i + 2i = 3i ` , and so that becomes
4246+ the value of the accumulator for the last iteration. On that iteration,
4247+ ` x ` is the last element, ` 3i ` , and ` 3i + 3i = 6i ` , which is our final
4248+ result for our sum. ` 1 + 2 + 3 = 6 ` , and that's the result we got.
4249+
4250+ Whew. ` fold ` can be a bit strange the first few times you see it, but once it
4251+ clicks, you can use it all over the place. Any time you have a list of things,
4252+ and you want a single result, ` fold ` is appropriate.
4253+
4254+ Consumers are important due to one additional property of iterators we haven't
4255+ talked about yet: laziness. Let's talk some more about iterators, and you'll
4256+ see why consumers matter.
4257+
4258+ ## Iterators
4259+
4260+ As we've said before, an iterator is something that we can call the ` .next() `
4261+ method on repeatedly, and it gives us a sequence of things. Because you need
4262+ to call the method, this means that iterators are ** lazy** . This code, for
4263+ example, does not actually generate the numbers ` 1-100 ` , and just creates a
4264+ value that represents the sequence:
4265+
4266+ ``` {rust}
4267+ let nums = range(1i, 100i);
4268+ ```
4269+
4270+ Since we didn't do anything with the range, it didn't generate the sequence.
4271+ Once we add the consumer:
4272+
4273+ ``` {rust}
4274+ let nums = range(1i, 100i).collect::<Vec<int>>();
4275+ ```
4276+
4277+ Now, ` collect() ` will require that ` range() ` give it some numbers, and so
4278+ it will do the work of generating the sequence.
4279+
4280+ ` range ` is one of two basic iterators that you'll see. The other is ` iter() ` ,
4281+ which you've used before. ` iter() ` can turn a vector into a simple iterator
4282+ that gives you each element in turn:
4283+
4284+ ``` {rust}
4285+ let nums = [1i, 2i, 3i];
4286+
4287+ for num in nums.iter() {
4288+ println!("{}", num);
4289+ }
4290+ ```
4291+
4292+ These two basic iterators should serve you well. There are some more
4293+ advanced iterators, including ones that are infinite. Like ` count ` :
4294+
4295+ ``` {rust}
4296+ std::iter::count(1i, 5i);
4297+ ```
4298+
4299+ This iterator counts up from one, adding five each time. It will give
4300+ you a new integer every time, forever. Well, technically, until the
4301+ maximum number that an ` int ` can represent. But since iterators are lazy,
4302+ that's okay! You probably don't want to use ` collect() ` on it, though...
4303+
4304+ That's enough about iterators. Iterator adapters are the last concept
4305+ we need to talk about with regards to iterators. Let's get to it!
4306+
4307+ ## Iterator adapters
4308+
4309+ "Iterator adapters" take an iterator and modify it somehow, producing
4310+ a new iterator. The simplest one is called ` map ` :
4311+
4312+ ``` {rust,ignore}
4313+ range(1i, 100i).map(|x| x + 1i);
4314+ ```
4315+
4316+ ` map ` is called upon another iterator, and produces a new iterator where each
4317+ element reference has the closure it's been given as an argument called on it.
4318+ So this would give us the numbers from ` 2-101 ` . Well, almost! If you
4319+ compile the example, you'll get a warning:
4320+
4321+ ``` {notrust,ignore}
4322+ 2:37 warning: unused result which must be used: iterator adaptors are lazy and
4323+ do nothing unless consumed, #[warn(unused_must_use)] on by default
4324+ range(1i, 100i).map(|x| x + 1i);
4325+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4326+ ```
4327+
4328+ Laziness strikes again! That closure will never execute. This example
4329+ doesn't print any numbers:
4330+
4331+ ``` {rust,ignore}
4332+ range(1i, 100i).map(|x| println!("{}", x));
4333+ ```
4334+
4335+ If you are trying to execute a closure on an iterator for its side effects,
4336+ just use ` for ` instead.
4337+
4338+ There are tons of interesting iterator adapters. ` take(n) ` will get the
4339+ first ` n ` items out of an iterator, and return them as a list. Let's
4340+ try it out with our infinite iterator from before, ` count() ` :
4341+
4342+ ``` {rust}
4343+ for i in std::iter::count(1i, 5i).take(5) {
4344+ println!("{}", i);
4345+ }
4346+ ```
4347+
4348+ This will print
4349+
4350+ ``` {notrust,ignore}
4351+ 1
4352+ 6
4353+ 11
4354+ 16
4355+ 21
4356+ ```
4357+
4358+ ` filter() ` is an adapter that takes a closure as an argument. This closure
4359+ returns ` true ` or ` false ` . The new iterator ` filter() ` produces returns
4360+ only the elements that that closure returned ` true ` for:
4361+
4362+ ``` {rust}
4363+ for i in range(1i, 100i).filter(|x| x % 2 == 0) {
4364+ println!("{}", i);
4365+ }
4366+ ```
4367+
4368+ This will print all of the even numbers between one and a hundred.
4369+
4370+ You can chain all three things together: start with an iterator, adapt it
4371+ a few times, and then consume the result. Check it out:
4372+
4373+ ``` {rust}
4374+ range(1i, 1000i)
4375+ .filter(|x| x % 2 == 0)
4376+ .filter(|x| x % 3 == 0)
4377+ .take(5)
4378+ .collect::<Vec<int>>();
4379+ ```
4380+
4381+ This will give you a vector containing ` 6 ` , ` 12 ` , ` 18 ` , ` 24 ` , and ` 30 ` .
4382+
4383+ This is just a small taste of what iterators, iterator adapters, and consumers
4384+ can help you with. There are a number of really useful iterators, and you can
4385+ write your own as well. Iterators provide a safe, efficient way to manipulate
4386+ all kinds of lists. They're a little unusual at first, but if you play with
4387+ them, you'll get hooked. For a full list of the different iterators and
4388+ consumers, check out the [ iterator module documentation] ( std/iter/index.html ) .
40554389
40564390# Generics
40574391
0 commit comments