about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--doc/tutorial.md91
1 files changed, 49 insertions, 42 deletions
diff --git a/doc/tutorial.md b/doc/tutorial.md
index 2d43d19deff..1695977e627 100644
--- a/doc/tutorial.md
+++ b/doc/tutorial.md
@@ -545,8 +545,8 @@ You can define your own syntax extensions with the macro system. For details, se
 
 ## Conditionals
 
-We've seen `if` pass by a few times already. To recap, braces are
-compulsory, an optional `else` clause can be appended, and multiple
+We've seen `if` expressions a few times already. To recap, braces are
+compulsory, an `if` can have an optional `else` clause, and multiple
 `if`/`else` constructs can be chained together:
 
 ~~~~
@@ -559,10 +559,10 @@ if false {
 }
 ~~~~
 
-The condition given to an `if` construct *must* be of type boolean (no
-implicit conversion happens). If the arms return a value, this value
-must be of the same type for every arm in which control reaches the
-end of the block:
+The condition given to an `if` construct *must* be of type `bool` (no
+implicit conversion happens). If the arms are blocks that have a
+value, this value must be of the same type for every arm in which
+control reaches the end of the block:
 
 ~~~~
 fn signum(x: int) -> int {
@@ -575,9 +575,10 @@ fn signum(x: int) -> int {
 ## Pattern matching
 
 Rust's `match` construct is a generalized, cleaned-up version of C's
-`switch` construct. You provide it with a value and a number of *arms*,
-each labelled with a pattern, and the code will attempt to match each pattern
-in order. For the first one that matches, the arm is executed.
+`switch` construct. You provide it with a value and a number of
+*arms*, each labelled with a pattern, and the code compares the value
+against each pattern in order until one matches. The matching pattern
+executes its corresponding arm.
 
 ~~~~
 # let my_number = 1;
@@ -589,15 +590,19 @@ match my_number {
 }
 ~~~~
 
-There is no 'falling through' between arms, as in C—only one arm is
-executed, and it doesn't have to explicitly `break` out of the
+Unlike in C, there is no 'falling through' between arms: only one arm
+executes, and it doesn't have to explicitly `break` out of the
 construct when it is finished.
 
-The part to the left of the arrow `=>` is called the *pattern*. Literals are
-valid patterns and will match only their own value. The pipe operator
-(`|`) can be used to assign multiple patterns to a single arm. Ranges
-of numeric literal patterns can be expressed with two dots, as in `M..N`. The
-underscore (`_`) is a wildcard pattern that matches everything.
+A `match` arm consists of a *pattern*, then an arrow `=>`, followed by
+an *action* (expression). Literals are valid patterns and match only
+their own value. A single arm may match multiple different patterns by
+combining them with the pipe operator (`|`), so long as every pattern
+binds the same set of variables. Ranges of numeric literal patterns
+can be expressed with two dots, as in `M..N`. The underscore (`_`) is
+a wildcard pattern that matches any single value. The asterisk (`*`)
+is a different wildcard that can match one or more fields in an `enum`
+variant.
 
 The patterns in an match arm are followed by a fat arrow, `=>`, then an
 expression to evaluate. Each case is separated by commas. It's often
@@ -612,13 +617,14 @@ match my_number {
 }
 ~~~
 
-`match` constructs must be *exhaustive*: they must have an arm covering every
-possible case. For example, if the arm with the wildcard pattern was left off
-in the above example, the typechecker would reject it.
+`match` constructs must be *exhaustive*: they must have an arm
+covering every possible case. For example, the typechecker would
+reject the previous example if the arm with the wildcard pattern was
+omitted.
 
-A powerful application of pattern matching is *destructuring*, where
-you use the matching to get at the contents of data types. Remember
-that `(float, float)` is a tuple of two floats:
+A powerful application of pattern matching is *destructuring*:
+matching in order to bind names to the contents of data
+types. Remember that `(float, float)` is a tuple of two floats:
 
 ~~~~
 fn angle(vector: (float, float)) -> float {
@@ -631,37 +637,39 @@ fn angle(vector: (float, float)) -> float {
 }
 ~~~~
 
-A variable name in a pattern matches everything, *and* binds that name
-to the value of the matched thing inside of the arm block. Thus, `(0f,
+A variable name in a pattern matches any value, *and* binds that name
+to the value of the matched value inside of the arm's action. Thus, `(0f,
 y)` matches any tuple whose first element is zero, and binds `y` to
 the second element. `(x, y)` matches any tuple, and binds both
-elements to a variable.
+elements to variables.
 
-Any `match` arm can have a guard clause (written `if EXPR`), which is
-an expression of type `bool` that determines, after the pattern is
-found to match, whether the arm is taken or not. The variables bound
-by the pattern are available in this guard expression.
+Any `match` arm can have a guard clause (written `if EXPR`), called a
+*pattern guard*, which is an expression of type `bool` that
+determines, after the pattern is found to match, whether the arm is
+taken or not. The variables bound by the pattern are in scope in this
+guard expression. The first arm in the `angle` example shows an
+example of a pattern guard.
 
 You've already seen simple `let` bindings, but `let` is a little
-fancier than you've been led to believe. It too supports destructuring
-patterns. For example, you can say this to extract the fields from a
-tuple, introducing two variables, `a` and `b`.
+fancier than you've been led to believe. It, too, supports destructuring
+patterns. For example, you can write this to extract the fields from a
+tuple, introducing two variables at once: `a` and `b`.
 
 ~~~~
 # fn get_tuple_of_two_ints() -> (int, int) { (1, 1) }
 let (a, b) = get_tuple_of_two_ints();
 ~~~~
 
-Let bindings only work with _irrefutable_ patterns, that is, patterns
+Let bindings only work with _irrefutable_ patterns: that is, patterns
 that can never fail to match. This excludes `let` from matching
-literals and most enum variants.
+literals and most `enum` variants.
 
 ## Loops
 
-`while` produces a loop that runs as long as its given condition
-(which must have type `bool`) evaluates to true. Inside a loop, the
-keyword `break` can be used to abort the loop, and `loop` can be used
-to abort the current iteration and continue with the next.
+`while` denotes a loop that iterates as long as its given condition
+(which must have type `bool`) evaluates to `true`. Inside a loop, the
+keyword `break` aborts the loop, and `loop` aborts the current
+iteration and continues with the next.
 
 ~~~~
 let mut cake_amount = 8;
@@ -670,7 +678,7 @@ while cake_amount > 0 {
 }
 ~~~~
 
-`loop` is the preferred way of writing `while true`:
+`loop` denotes an infinite loop, and is the preferred way of writing `while true`:
 
 ~~~~
 let mut x = 5;
@@ -684,9 +692,8 @@ loop {
 This code prints out a weird sequence of numbers and stops as soon as
 it finds one that can be divided by five.
 
-For more involved iteration, such as going over the elements of a
-collection, Rust uses higher-order functions. We'll come back to those
-in a moment.
+For more involved iteration, such as enumerating the elements of a
+collection, Rust uses [higher-order functions](#closures).
 
 # Data structures