fix some TODOs

This commit is contained in:
steveklabnik
2017-04-01 11:45:12 -04:00
committed by Carol (Nichols || Goulding)
parent 2f56ea9872
commit cebc14efe6

View File

@@ -173,11 +173,50 @@ This will print `Current location: (3, 5)`.
### `while let`
TODO: add a `while let` example
A similar construction to `if let` is `while let`; this allows you to do
a `while` loop while matching a pattern. For example:
```rust
let mut stack = Vec::new();
stack.push(1);
stack.push(2);
stack.push(3);
while let Some(top) = stack.pop() {
// Prints 3, 2, 1
println!("{}", top);
}
```
Here, the `pop` method takes the last element out of the vector and returns `Some(value)`.
If the vector is empty, it returns `None`. We can use `while let` to pop every element
off this way.
### `for` loops
TODO: add a `for` loop example
Looping with `for`, as we discussed in Chapter 3, is the most common loop construction in
Rust code. But what we didn't talk about in that chapter was that `for` takes a pattern.
For example, the `enumerate` method adapts an iterator to not only produce a value, but
a tuple with the value and its index. We can use a pattern to destructure that tuple:
```rust
let v = vec![1, 2, 3];
for (index, value) in v {
println!("{} is at index {}", value, index);
}
```
This will print:
```text
1 is at index 0
2 is at index 1
3 is at index 2
```
The `(index, value)` construction there is a pattern.
## Refutability: Whether a Pattern Might Fail to Match
@@ -291,8 +330,6 @@ more like destructuring?
### Named Variables and the Underscore Pattern
TODO: variable name always matches any value, underscore ignores everything, say the word "wildcard" somewhere about `_`
Usually, Rust will warn you if you create a variable but don't use it anywhere,
since that could be a bug. If you're prototyping or just starting a project,
though, you might create a variable that you'll use eventually, but temporarily
@@ -311,7 +348,8 @@ fn main() {
```
Similarly with patterns as function parameters, if we didn't want to use the
argument in the body of our function, we could use `_` for example:
argument in the body of our function, we could use `_`, also known as a
'wildcard' for example:
```rust
fn foo(_: i32) {
@@ -326,6 +364,32 @@ parameters like it would if we had given it a name.
TODO: names starting with underscores behave the same as names not starting with underscores, aside from not getting an unused warning. Underscore is special; it drops right away. Example?
There's one more bit of subtlety here; `_x` and `_` have different behavior. That
is, `_x` still binds to the variable of that name, but `_` doesn't bind at all.
For example, this will produce an error:
```rust,ignore
let s = String::from("Hello!");
let _s = s;
println!("{}", s);
```
Specifically, "use of moved value". When we assign `s` to `_s`, it moves, and so
`s` is no longer valid. However...
```rust
let s = String::from("Hello!");
let _ = s;
println!("{}", s);
```
This works just fine. Becuase we never bind `s` to anything, it's not moved.
### Multiple patterns
You can match multiple patterns with `|`:
@@ -430,7 +494,22 @@ fn main() {
}
```
TODO: add enum destructuring example
It's also common to use destructuring with `enums`. For example, the `is_none` method
on `Option<T>` returns `true` if the `Option<T>` is `None`, and false if it is `Some`.
Here's what it looks like:
```rust,ignore
impl<T> Option<T> {
pub fn is_some(&self) -> bool {
match *self {
Some(_) => true,
None => false,
}
}
}
```
The `Some(_)` pattern will match any value, as long as it's `Some`.
We can mix, match, and nest destructuring patterns: we can do
something complicated like this example where we nest tuples inside of
@@ -485,21 +564,24 @@ match origin {
}
```
TODO: explain this example with `..` in the middle that works:
`..` will expand to as many values as it needs to be. For example:
```rust
fn main() {
let numbers = (2, 4, 8, 16, 32);
match numbers {
(first, .., fifth) => {
println!("Some numbers: {}, {}", first, fifth)
(first, .., last) => {
println!("Some numbers: {}, {}", first, last);
},
}
}
```
TODO: explain this example with `..` twice that doesn't work because it's ambiguous:
Here, we have the first and last value matched, with `first` and `last`. The `..` will
match all of the things in the middle.
This doesn't always work, though. Consider this:
```rust,ignore
fn main() {
@@ -513,7 +595,7 @@ fn main() {
}
```
error:
We get this error:
```text
error: `..` can only be used once per tuple or tuple struct pattern
@@ -523,6 +605,10 @@ error: `..` can only be used once per tuple or tuple struct pattern
| ^^
```
It's not possible to determine that this is _actually_ the second value, like we gave
the name. What if both `..` matched two elements? It'd be the third, value, not the second.
Since this is ambiguous, Rust disallows it.
### Matching Ranges of Values with `...`
You can match a range of values with `...`:
@@ -553,8 +639,6 @@ This will print `early ASCII letter`.
### Extra Conditionals with Match Guards
TODO: is this really part of pattern syntax?
You can introduce *match guards* with `if`:
```rust