@@ -4227,9 +4227,343 @@ Doing this is not particularly common, but every once in a while, it's useful.
4227
4227
That's all you need to get the hang of closures! Closures are a little bit
4228
4228
strange at first, but once you're used to using them, you'll miss them in any
4229
4229
language 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.
4231
4231
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 ) .
4233
4567
4234
4568
# Generics
4235
4569
0 commit comments