diff --git a/src/if-let.md b/src/if-let.md index 8234910..25c5b11 100644 --- a/src/if-let.md +++ b/src/if-let.md @@ -31,7 +31,7 @@ if let Some(x) = some_option { ``` `if let` takes a pattern and an expression, separated by an `=`. It works -exactly like a `match`, where the expression is given to the `match`, and the +exactly like a `match`, where the expression is given to the `match` and the pattern is its first arm. In other words, you can think of `if let` as syntax sugar: @@ -46,7 +46,7 @@ match expression { } ``` -And in fact, we can include an `else`, too, and it becomes the body of the `_` +And in fact, we can include an `else` and it becomes the body of the `_` case: ```rust,ignore diff --git a/src/match.md b/src/match.md index 69afb99..d3f2417 100644 --- a/src/match.md +++ b/src/match.md @@ -38,8 +38,9 @@ Next, we have a "match arm". That's the part that looks like `pattern => code,`. We can have as many arms as we need to: our `match` above has two arms. An arm has two parts: a pattern, and some code. When the `match` expression executes, it compares the condition against the pattern of each arm, -in turn. If the pattern matches the condition, it executes the associated code. -If it doesn't match, it continues to the next arm. +in turn. If the pattern matches the condition, the associated code is executed, +and the rest of the patterns are not checked. If it doesn't match, execution +continues to the next arm. Let's examine the first execution of `plus_one()` in more detail. In the above example, `x` will be `Some(5)`. Let's compare that against each arm: @@ -54,7 +55,7 @@ Does `Some(5)` match `None`? No, it's the wrong variant. So let's continue. Some(i) => Some(i + 1), ``` -Does `Some(5)` match `Some(i)`. Why yes it does! We have the same variant. But +Does `Some(5)` match `Some(i)`? Why yes it does! We have the same variant. But what about `i`? In a pattern like this, we can declare new bindings, similarly to what we did with `let`. So in this case, the code part of the match arm will have a binding, `i`, which corresponds to the `5`. @@ -126,10 +127,14 @@ match some_u8_value { 5 => println!("five"), 6 => println!("six"), 7 => println!("seven"), + // We won't write out all of the arms here, but imagine that there are more + // arms corresponding to the rest of the numbers. + 254 => println!("two-hundred and fifty-four"), + 255 => println!("two-hundred and fifty-five"), } ``` -Even though a `u8` can only have valid values of zero through seven, Rust isn't +Even though a `u8` can only have valid values of zero through 255, Rust isn't quite smart enough to understand we've covered all the cases. In order to fix this, we can use a special pattern, `_`: @@ -144,6 +149,9 @@ match some_u8_value { 5 => println!("five"), 6 => println!("six"), 7 => println!("seven"), + // ... + 254 => println!("two-hundred and fifty-four"), + 255 => println!("two-hundred and fifty-five"), _ => panic!("can't ever happen"), } ``` diff --git a/src/option.md b/src/option.md index c22288d..f9b0ce0 100644 --- a/src/option.md +++ b/src/option.md @@ -8,7 +8,7 @@ but it's also about which features you leave out. Rust does not have a feature that is in many other languages: 'null'. In languages with this feature, variables can have two states: null or not-null. -The inventor of this concept, Tony Hoare, has this to say: +The inventor of this concept has this to say: > I call it my billion-dollar mistake. At that time, I was designing the first > comprehensive type system for references in an object-oriented language. My @@ -18,6 +18,8 @@ The inventor of this concept, Tony Hoare, has this to say: > implement. This has led to innumerable errors, vulnerabilities, and system > crashes, which have probably caused a billion dollars of pain and damage in > the last forty years. +> +> - Tony Hoare "Null References: The Billion Dollar Mistake" The problem with null values is twofold: first, a value can be null or not, at any time. The second is that if you try to use a value that's null, you'll get @@ -38,7 +40,7 @@ enum Option { } ``` -This type is [provided in the standard library][option], and is so useful that +This type is [provided by the standard library][option], and is so useful that it's even in the prelude; you don't need to import it explicitly. Furthermore, so are its variants: you can say `Some` and `None` directly, without prefixing them with `Option::`. diff --git a/src/patterns.md b/src/patterns.md index 5925d26..d696477 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -40,10 +40,10 @@ This prints `one or two`. ## ref and ref mut -Usually, when you match against a pattern, bindings: are bound by value. +Usually, when you match against a pattern, bindings are bound by value. This means you'll end up moving the value out: -```rust +```rust,ignore let name = Some(String::from("Bors")); match name { @@ -51,7 +51,8 @@ match name { None => (), } -// name is moved here +// name is moved here. This line will fail to compile: +println!("name is: {:?}", name); ``` If you'd prefer to bind `name` by reference, use the `ref` keyword: @@ -65,7 +66,8 @@ match name { } // name is not moved here; the match only took a reference to its data rather -// than moving it +// than moving it. This will work: +println!("name is: {:?}", name); ``` And for a mutable reference, `ref mut`: @@ -204,6 +206,7 @@ let x = Some(5); match x { Some(x) if x < 5 => println!("less than five: {}", x), + Some(x) => println!("{}", x), None => (), } ```