Rollup merge of #24281 - steveklabnik:lol_editing, r=alexcrichton

more more more
This commit is contained in:
Manish Goregaokar 2015-04-11 19:05:09 +05:30
commit df8360f4fc
9 changed files with 161 additions and 311 deletions

View File

@ -7,38 +7,39 @@
* [Learn Rust](learn-rust.md)
* [Effective Rust](effective-rust.md)
* [The Stack and the Heap](the-stack-and-the-heap.md)
* [`Debug` and `Display`](debug-and-display.md)
* [Debug and Display](debug-and-display.md)
* [Testing](testing.md)
* [Documentation](documentation.md)
* [Iterators](iterators.md)
* [Concurrency](concurrency.md)
* [Error Handling](error-handling.md)
* [FFI](ffi.md)
* [`Deref` coercions](deref-coercions.md)
* [Deref coercions](deref-coercions.md)
* [Syntax and Semantics](syntax-and-semantics.md)
* [Variable Bindings](variable-bindings.md)
* [Functions](functions.md)
* [Primitive Types](primitive-types.md)
* [Comments](comments.md)
* [Structs](structs.md)
* [Mutability](mutability.md)
* [Method Syntax](method-syntax.md)
* [Enums](enums.md)
* [`if`](if.md)
* [Match](match.md)
* [Patterns](patterns.md)
* [`for` loops](for-loops.md)
* [`while` loops](while-loops.md)
* [if](if.md)
* [for loops](for-loops.md)
* [while loops](while-loops.md)
* [Ownership](ownership.md)
* [References and Borrowing](references-and-borrowing.md)
* [Lifetimes](lifetimes.md)
* [Mutability](mutability.md)
* [Move semantics](move-semantics.md)
* [Enums](enums.md)
* [Match](match.md)
* [Patterns](patterns.md)
* [Structs](structs.md)
* [Method Syntax](method-syntax.md)
* [Drop](drop.md)
* [Vectors](vectors.md)
* [Strings](strings.md)
* [Traits](traits.md)
* [Operators and Overloading](operators-and-overloading.md)
* [Generics](generics.md)
* [if let](if-let.md)
* [Trait Objects](trait-objects.md)
* [Closures](closures.md)
* [Universal Function Call Syntax](ufcs.md)
@ -63,5 +64,6 @@
* [Link args](link-args.md)
* [Benchmark Tests](benchmark-tests.md)
* [Box Syntax and Patterns](box-syntax-and-patterns.md)
* [Slice Patterns](slice-patterns.md)
* [Glossary](glossary.md)
* [Academic Research](academic-research.md)

View File

@ -1,3 +1,3 @@
% `Debug` and `Display`
% Debug and Display
Coming soon!

View File

@ -1,10 +1,10 @@
% `for` Loops
% for Loops
The `for` loop is used to loop a particular number of times. Rust's `for` loops
work a bit differently than in other systems languages, however. Rust's `for`
loop doesn't look like this "C-style" `for` loop:
The `for` loop is used to loop a particular number of times. Rusts `for` loops
work a bit differently than in other systems languages, however. Rusts `for`
loop doesnt look like this “C-style” `for` loop:
```{c}
```c
for (x = 0; x < 10; x++) {
printf( "%d\n", x );
}
@ -12,7 +12,7 @@ for (x = 0; x < 10; x++) {
Instead, it looks like this:
```{rust}
```rust
for x in 0..10 {
println!("{}", x); // x: i32
}
@ -20,25 +20,24 @@ for x in 0..10 {
In slightly more abstract terms,
```{ignore}
```ignore
for var in expression {
code
}
```
The expression is an iterator, which we will discuss in more depth later in the
guide. The iterator gives back a series of elements. Each element is one
iteration of the loop. That value is then bound to the name `var`, which is
valid for the loop body. Once the body is over, the next value is fetched from
the iterator, and we loop another time. When there are no more values, the
`for` loop is over.
The expression is an [iterator][iterator]. The iterator gives back a series of
elements. Each element is one iteration of the loop. That value is then bound
to the name `var`, which is valid for the loop body. Once the body is over, the
next value is fetched from the iterator, and we loop another time. When there
are no more values, the `for` loop is over.
[iterator]: iterators.html
In our example, `0..10` is an expression that takes a start and an end position,
and gives an iterator over those values. The upper bound is exclusive, though,
so our loop will print `0` through `9`, not `10`.
Rust does not have the "C-style" `for` loop on purpose. Manually controlling
Rust does not have the “C-style” `for` loop on purpose. Manually controlling
each element of the loop is complicated and error prone, even for experienced C
developers.
We'll talk more about `for` when we cover *iterators*, later in the Guide.

3
src/doc/trpl/if-let.md Normal file
View File

@ -0,0 +1,3 @@
% if let
COMING SOON

View File

@ -1,10 +1,10 @@
% `if`
% if
Rust's take on `if` is not particularly complex, but it's much more like the
`if` you'll find in a dynamically typed language than in a more traditional
systems language. So let's talk about it, to make sure you grasp the nuances.
Rusts take on `if` is not particularly complex, but its much more like the
`if` youll find in a dynamically typed language than in a more traditional
systems language. So lets talk about it, to make sure you grasp the nuances.
`if` is a specific form of a more general concept, the *branch*. The name comes
`if` is a specific form of a more general concept, the branch. The name comes
from a branch in a tree: a decision point, where depending on a choice,
multiple paths can be taken.
@ -20,11 +20,11 @@ if x == 5 {
If we changed the value of `x` to something else, this line would not print.
More specifically, if the expression after the `if` evaluates to `true`, then
the block is executed. If it's `false`, then it is not.
the block is executed. If its `false`, then it is not.
If you want something to happen in the `false` case, use an `else`:
```{rust}
```rust
let x = 5;
if x == 5 {
@ -50,8 +50,7 @@ if x == 5 {
This is all pretty standard. However, you can also do this:
```{rust}
```rust
let x = 5;
let y = if x == 5 {
@ -63,95 +62,12 @@ let y = if x == 5 {
Which we can (and probably should) write like this:
```{rust}
```rust
let x = 5;
let y = if x == 5 { 10 } else { 15 }; // y: i32
```
This reveals two interesting things about Rust: it is an expression-based
language, and semicolons are different from semicolons in other 'curly brace
and semicolon'-based languages. These two things are related.
## Expressions vs. Statements
Rust is primarily an expression based language. There are only two kinds of
statements, and everything else is an expression.
So what's the difference? Expressions return a value, and statements do not.
In many languages, `if` is a statement, and therefore, `let x = if ...` would
make no sense. But in Rust, `if` is an expression, which means that it returns
a value. We can then use this value to initialize the binding.
Speaking of which, bindings are a kind of the first of Rust's two statements.
The proper name is a *declaration statement*. So far, `let` is the only kind
of declaration statement we've seen. Let's talk about that some more.
In some languages, variable bindings can be written as expressions, not just
statements. Like Ruby:
```{ruby}
x = y = 5
```
In Rust, however, using `let` to introduce a binding is _not_ an expression. The
following will produce a compile-time error:
```{ignore}
let x = (let y = 5); // expected identifier, found keyword `let`
```
The compiler is telling us here that it was expecting to see the beginning of
an expression, and a `let` can only begin a statement, not an expression.
Note that assigning to an already-bound variable (e.g. `y = 5`) is still an
expression, although its value is not particularly useful. Unlike C, where an
assignment evaluates to the assigned value (e.g. `5` in the previous example),
in Rust the value of an assignment is the unit type `()` (which we'll cover later).
The second kind of statement in Rust is the *expression statement*. Its
purpose is to turn any expression into a statement. In practical terms, Rust's
grammar expects statements to follow other statements. This means that you use
semicolons to separate expressions from each other. This means that Rust
looks a lot like most other languages that require you to use semicolons
at the end of every line, and you will see semicolons at the end of almost
every line of Rust code you see.
What is this exception that makes us say "almost"? You saw it already, in this
code:
```{rust}
let x = 5;
let y: i32 = if x == 5 { 10 } else { 15 };
```
Note that I've added the type annotation to `y`, to specify explicitly that I
want `y` to be an integer.
This is not the same as this, which won't compile:
```{ignore}
let x = 5;
let y: i32 = if x == 5 { 10; } else { 15; };
```
Note the semicolons after the 10 and 15. Rust will give us the following error:
```text
error: mismatched types: expected `i32`, found `()` (expected i32, found ())
```
We expected an integer, but we got `()`. `()` is pronounced *unit*, and is a
special type in Rust's type system. In Rust, `()` is _not_ a valid value for a
variable of type `i32`. It's only a valid value for variables of the type `()`,
which aren't very useful. Remember how we said statements don't return a value?
Well, that's the purpose of unit in this case. The semicolon turns any
expression into a statement by throwing away its value and returning unit
instead.
There's one more time in which you won't see a semicolon at the end of a line
of Rust code. For that, we'll need our next concept: functions.
TODO: `if let`
This works because `if` is an expression. The value of the expression is the
value of the last expression in whichever branch was chosen. An `if` without an
`else` always results in `()` as the value.

View File

@ -1,13 +1,13 @@
% Match
Often, a simple `if`/`else` isn't enough, because you have more than two
Often, a simple `if`/`else` isnt enough, because you have more than two
possible options. Also, `else` conditions can get incredibly complicated, so
what's the solution?
whats the solution?
Rust has a keyword, `match`, that allows you to replace complicated `if`/`else`
groupings with something more powerful. Check it out:
```{rust}
```rust
let x = 5;
match x {
@ -21,11 +21,14 @@ match x {
```
`match` takes an expression and then branches based on its value. Each *arm* of
the branch is of the form `val => expression`. When the value matches, that arm's
expression will be evaluated. It's called `match` because of the term 'pattern
matching', which `match` is an implementation of.
the branch is of the form `val => expression`. When the value matches, that arms
expression will be evaluated. Its called `match` because of the term pattern
matching, which `match` is an implementation of. Theres an [entire section on
patterns][patterns] coming up next, that covers all the options that fit here.
So what's the big advantage here? Well, there are a few. First of all, `match`
[patterns]: patterns.html
So whats the big advantage here? Well, there are a few. First of all, `match`
enforces *exhaustiveness checking*. Do you see that last arm, the one with the
underscore (`_`)? If we remove that arm, Rust will give us an error:
@ -36,121 +39,24 @@ error: non-exhaustive patterns: `_` not covered
In other words, Rust is trying to tell us we forgot a value. Because `x` is an
integer, Rust knows that it can have a number of different values for example,
`6`. Without the `_`, however, there is no arm that could match, and so Rust refuses
to compile. `_` acts like a *catch-all arm*. If none of the other arms match,
to compile. `_` acts like a catch-all arm. If none of the other arms match,
the arm with `_` will, and since we have this catch-all arm, we now have an arm
for every possible value of `x`, and so our program will compile successfully.
`match` statements also destructure enums, as well. Remember this code from the
section on enums?
```{rust}
use std::cmp::Ordering;
fn cmp(a: i32, b: i32) -> Ordering {
if a < b { Ordering::Less }
else if a > b { Ordering::Greater }
else { Ordering::Equal }
}
fn main() {
let x = 5;
let y = 10;
let ordering = cmp(x, y);
if ordering == Ordering::Less {
println!("less");
} else if ordering == Ordering::Greater {
println!("greater");
} else if ordering == Ordering::Equal {
println!("equal");
}
}
```
We can re-write this as a `match`:
```{rust}
use std::cmp::Ordering;
fn cmp(a: i32, b: i32) -> Ordering {
if a < b { Ordering::Less }
else if a > b { Ordering::Greater }
else { Ordering::Equal }
}
fn main() {
let x = 5;
let y = 10;
match cmp(x, y) {
Ordering::Less => println!("less"),
Ordering::Greater => println!("greater"),
Ordering::Equal => println!("equal"),
}
}
```
This version has way less noise, and it also checks exhaustively to make sure
that we have covered all possible variants of `Ordering`. With our `if`/`else`
version, if we had forgotten the `Greater` case, for example, our program would
have happily compiled. If we forget in the `match`, it will not. Rust helps us
make sure to cover all of our bases.
`match` expressions also allow us to get the values contained in an `enum`
(also known as destructuring) as follows:
```{rust}
enum OptionalInt {
Value(i32),
Missing,
}
fn main() {
let x = OptionalInt::Value(5);
let y = OptionalInt::Missing;
match x {
OptionalInt::Value(n) => println!("x is {}", n),
OptionalInt::Missing => println!("x is missing!"),
}
match y {
OptionalInt::Value(n) => println!("y is {}", n),
OptionalInt::Missing => println!("y is missing!"),
}
}
```
That is how you can get and use the values contained in `enum`s.
It can also allow us to handle errors or unexpected computations; for example, a
function that is not guaranteed to be able to compute a result (an `i32` here)
could return an `OptionalInt`, and we would handle that value with a `match`.
As you can see, `enum` and `match` used together are quite useful!
`match` is also an expression, which means we can use it on the right-hand
side of a `let` binding or directly where an expression is used. We could
also implement the previous example like this:
side of a `let` binding or directly where an expression is used:
```{rust}
use std::cmp::Ordering;
```rust
let x = 5;
fn cmp(a: i32, b: i32) -> Ordering {
if a < b { Ordering::Less }
else if a > b { Ordering::Greater }
else { Ordering::Equal }
}
fn main() {
let x = 5;
let y = 10;
println!("{}", match cmp(x, y) {
Ordering::Less => "less",
Ordering::Greater => "greater",
Ordering::Equal => "equal",
});
}
let numer = match x {
1 => "one",
2 => "two",
3 => "three",
4 => "four",
5 => "five",
_ => "something else",
};
```
Sometimes, it's a nice pattern.
Sometimes, its a nice way of converting things.

View File

@ -1,13 +1,16 @@
% Patterns
We've made use of patterns a few times in the guide: first with `let` bindings,
then with `match` statements. Let's go on a whirlwind tour of all of the things
patterns can do!
Patterns are quite common in Rust. We use them in [variable
bindings][bindings], [match statements][match], and other places, too. Lets go
on a whirlwind tour of all of the things patterns can do!
[bindings]: variable-bindings.html
[match]: match.html
A quick refresher: you can match against literals directly, and `_` acts as an
*any* case:
any case:
```{rust}
```rust
let x = 1;
match x {
@ -18,9 +21,11 @@ match x {
}
```
# Multiple patterns
You can match multiple patterns with `|`:
```{rust}
```rust
let x = 1;
match x {
@ -30,9 +35,11 @@ match x {
}
```
# Ranges
You can match a range of values with `...`:
```{rust}
```rust
let x = 1;
match x {
@ -43,10 +50,12 @@ match x {
Ranges are mostly used with integers and single characters.
If you're matching multiple things, via a `|` or a `...`, you can bind
# Bindings
If youre matching multiple things, via a `|` or a `...`, you can bind
the value to a name with `@`:
```{rust}
```rust
let x = 1;
match x {
@ -55,10 +64,12 @@ match x {
}
```
If you're matching on an enum which has variants, you can use `..` to
# Ignoring variants
If youre matching on an enum which has variants, you can use `..` to
ignore the value and type in the variant:
```{rust}
```rust
enum OptionalInt {
Value(i32),
Missing,
@ -72,9 +83,11 @@ match x {
}
```
You can introduce *match guards* with `if`:
# Guards
```{rust}
You can introduce match guards with `if`:
```rust
enum OptionalInt {
Value(i32),
Missing,
@ -89,24 +102,11 @@ match x {
}
```
If you're matching on a pointer, you can use the same syntax as you declared it
with. First, `&`:
# ref and ref mut
```{rust}
let x = &5;
If you want to get a [reference][ref], use the `ref` keyword:
match x {
&val => println!("Got a value: {}", val),
}
```
Here, the `val` inside the `match` has type `i32`. In other words, the left-hand
side of the pattern destructures the value. If we have `&5`, then in `&val`, `val`
would be `5`.
If you want to get a reference, use the `ref` keyword:
```{rust}
```rust
let x = 5;
match x {
@ -114,11 +114,13 @@ match x {
}
```
[ref]: references-and-borrowing.html
Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref`
keyword _creates_ a reference, for use in the pattern. If you need a mutable
reference, `ref mut` will work in the same way:
```{rust}
```rust
let mut x = 5;
match x {
@ -126,10 +128,12 @@ match x {
}
```
If you have a struct, you can destructure it inside of a pattern:
# Destructuring
```{rust}
# #![allow(non_shorthand_field_patterns)]
If you have a compound data type, like a `struct`, you can destructure it
inside of a pattern:
```rust
struct Point {
x: i32,
y: i32,
@ -142,10 +146,9 @@ match origin {
}
```
If we only care about some of the values, we don't have to give them all names:
If we only care about some of the values, we dont have to give them all names:
```{rust}
# #![allow(non_shorthand_field_patterns)]
```rust
struct Point {
x: i32,
y: i32,
@ -160,8 +163,7 @@ match origin {
You can do this kind of match on any member, not just the first:
```{rust}
# #![allow(non_shorthand_field_patterns)]
```rust
struct Point {
x: i32,
y: i32,
@ -174,22 +176,16 @@ match origin {
}
```
If you want to match against a slice or array, you can use `&`:
This destructuring behavior works on any compound data type, like
[tuples][tuples] or [enums][enums].
```{rust}
# #![feature(slice_patterns)]
fn main() {
let v = vec!["match_this", "1"];
[tuples]: primitive-types.html#tuples
[enums]: enums.html
match &v[..] {
["match_this", second] => println!("The second element is {}", second),
_ => {},
}
}
```
# Mix and Match
Whew! That's a lot of different ways to match things, and they can all be
mixed and matched, depending on what you're doing:
Whew! Thats a lot of different ways to match things, and they can all be
mixed and matched, depending on what youre doing:
```{rust,ignore}
match x {

View File

@ -0,0 +1,18 @@
% Slice patterns
If you want to match against a slice or array, you can use `&` with the
`slice_patterns` feature:
```rust
#![feature(slice_patterns)]
fn main() {
let v = vec!["match_this", "1"];
match &v[..] {
["match_this", second] => println!("The second element is {}", second),
_ => {},
}
}
```

View File

@ -1,7 +1,6 @@
% `while` loops
% while loops
The other kind of looping construct in Rust is the `while` loop. It looks like
this:
Rust also has a `while` loop. It looks like this:
```{rust}
let mut x = 5; // mut x: u32
@ -9,45 +8,52 @@ let mut done = false; // mut done: bool
while !done {
x += x - 3;
println!("{}", x);
if x % 5 == 0 { done = true; }
if x % 5 == 0 {
done = true;
}
}
```
`while` loops are the correct choice when you're not sure how many times
`while` loops are the correct choice when youre not sure how many times
you need to loop.
If you need an infinite loop, you may be tempted to write this:
```{rust,ignore}
```rust,ignore
while true {
```
However, Rust has a dedicated keyword, `loop`, to handle this case:
```{rust,ignore}
```rust,ignore
loop {
```
Rust's control-flow analysis treats this construct differently than a
`while true`, since we know that it will always loop. The details of what
that _means_ aren't super important to understand at this stage, but in
general, the more information we can give to the compiler, the better it
can do with safety and code generation, so you should always prefer
`loop` when you plan to loop infinitely.
Rusts control-flow analysis treats this construct differently than a `while
true`, since we know that it will always loop. In general, the more information
we can give to the compiler, the better it can do with safety and code
generation, so you should always prefer `loop` when you plan to loop
infinitely.
## Ending iteration early
Let's take a look at that `while` loop we had earlier:
Lets take a look at that `while` loop we had earlier:
```{rust}
```rust
let mut x = 5;
let mut done = false;
while !done {
x += x - 3;
println!("{}", x);
if x % 5 == 0 { done = true; }
if x % 5 == 0 {
done = true;
}
}
```
@ -57,12 +63,14 @@ modifying iteration: `break` and `continue`.
In this case, we can write the loop in a better way with `break`:
```{rust}
```rust
let mut x = 5;
loop {
x += x - 3;
println!("{}", x);
if x % 5 == 0 { break; }
}
```
@ -72,7 +80,7 @@ We now loop forever with `loop` and use `break` to break out early.
`continue` is similar, but instead of ending the loop, goes to the next
iteration. This will only print the odd numbers:
```{rust}
```rust
for x in 0..10 {
if x % 2 == 0 { continue; }
@ -80,4 +88,6 @@ for x in 0..10 {
}
```
Both `continue` and `break` are valid in both kinds of loops.
Both `continue` and `break` are valid in both `while` loops and [`for` loops][for].
[for]: for-loops.html