Properly deal with Ordering in the guide

Now that it's been removed from the prelude, we need to treat things differently.

Fixes #17967
This commit is contained in:
Steve Klabnik 2014-12-23 13:31:43 -05:00 committed by Alex Crichton
parent 56290a0044
commit 76e3bc2338
4 changed files with 56 additions and 40 deletions

View File

@ -1106,10 +1106,17 @@ enum Ordering {
```
An `Ordering` can only be _one_ of `Less`, `Equal`, or `Greater` at any given
time. Here's an example:
time.
Because `Ordering` is provided by the standard library, we can use the `use`
keyword to use it in our code. We'll learn more about `use` later, but it's
used to bring names into scope.
Here's an example of how to use `Ordering`:
```{rust}
# use std::cmp::Ordering;
use std::cmp::Ordering;
fn cmp(a: int, b: int) -> Ordering {
if a < b { Ordering::Less }
else if a > b { Ordering::Greater }
@ -1132,18 +1139,25 @@ fn main() {
}
```
`cmp` is a function that compares two things, and returns an `Ordering`. We
return either `Less`, `Greater`, or `Equal`, depending on if the two values
are greater, less, or equal.
There's a symbol here we haven't seen before: the double colon (`::`).
This is used to indicate a namesapce. In this case, `Ordering` lives in
the `cmp` submodule of the `std` module. We'll talk more about modules
later in the guide. For now, all you need to know is that you can `use`
things from the standard library if you need them.
Okay, let's talk about the actual code in the example. `cmp` is a function that
compares two things, and returns an `Ordering`. We return either
`Ordering::Less`, `Ordering::Greater`, or `Ordering::Equal`, depending on if
the two values are greater, less, or equal. Note that each variant of the
`enum` is namespaced under the `enum` itself: it's `Ordering::Greater` not
`Greater`.
The `ordering` variable has the type `Ordering`, and so contains one of the
three values. We can then do a bunch of `if`/`else` comparisons to check
which one it is.
However, repeated `if`/`else` comparisons get quite tedious. Rust has a feature
that not only makes them nicer to read, but also makes sure that you never
miss a case. Before we get to that, though, let's talk about another kind of
enum: one with values.
three values. We can then do a bunch of `if`/`else` comparisons to check which
one it is. However, repeated `if`/`else` comparisons get quite tedious. Rust
has a feature that not only makes them nicer to read, but also makes sure that
you never miss a case. Before we get to that, though, let's talk about another
kind of enum: one with values.
This enum has two variants, one of which has a value:
@ -1176,18 +1190,19 @@ enum StringResult {
ErrorReason(String),
}
```
Where a `StringResult` is either a `StringOK`, with the result of a computation, or an
`ErrorReason` with a `String` explaining what caused the computation to fail. These kinds of
`enum`s are actually very useful and are even part of the standard library.
Where a `StringResult` is either a `StringResult::StringOK`, with the result of
a computation, or an `StringResult::ErrorReason` with a `String` explaining
what caused the computation to fail. These kinds of `enum`s are actually very
useful and are even part of the standard library.
Enum variants are namespaced under the enum names. For example, here is an example of using
our `StringResult`:
Here is an example of using our `StringResult`:
```rust
# enum StringResult {
# StringOK(String),
# ErrorReason(String),
# }
enum StringResult {
StringOK(String),
ErrorReason(String),
}
fn respond(greeting: &str) -> StringResult {
if greeting == "Hello" {
StringResult::StringOK("Good morning!".to_string())
@ -1197,10 +1212,7 @@ fn respond(greeting: &str) -> StringResult {
}
```
Notice that we need both the enum name and the variant name: `StringResult::StringOK`, but
we didn't need to with `Ordering` we just said `Greater` rather than `Ordering::Greater`.
There's a reason: the Rust prelude imports the variants of `Ordering` as well as the enum
itself. We can use the `use` keyword to do something similar with `StringResult`:
That's a lot of typing! We can use the `use` keyword to make it shorter:
```rust
use StringResult::StringOK;
@ -1222,12 +1234,11 @@ fn respond(greeting: &str) -> StringResult {
}
```
We'll learn more about `use` later, but it's used to bring names into scope. `use` declarations
must come before anything else, which looks a little strange in this example, since we `use`
the variants before we define them. Anyway, in the body of `respond`, we can just say `StringOK`
now, rather than the full `StringResult::StringOK`. Importing variants can be convenient, but can
also cause name conflicts, so do this with caution. It's considered good style to rarely import
variants for this reason.
`use` declarations must come before anything else, which looks a little strange in this example,
since we `use` the variants before we define them. Anyway, in the body of `respond`, we can just
say `StringOK` now, rather than the full `StringResult::StringOK`. Importing variants can be
convenient, but can also cause name conflicts, so do this with caution. It's considered good style
to rarely import variants for this reason.
As you can see, `enum`s with values are quite a powerful tool for data representation,
and can be even more useful when they're generic across types. Before we get to generics,
@ -1281,7 +1292,8 @@ for every possible value of `x`, and so our program will compile successfully.
section on enums?
```{rust}
# use std::cmp::Ordering;
use std::cmp::Ordering;
fn cmp(a: int, b: int) -> Ordering {
if a < b { Ordering::Less }
else if a > b { Ordering::Greater }
@ -1307,7 +1319,8 @@ fn main() {
We can re-write this as a `match`:
```{rust}
# use std::cmp::Ordering;
use std::cmp::Ordering;
fn cmp(a: int, b: int) -> Ordering {
if a < b { Ordering::Less }
else if a > b { Ordering::Greater }
@ -1368,7 +1381,8 @@ side of a `let` binding or directly where an expression is used. We could
also implement the previous line like this:
```{rust}
# use std::cmp::Ordering;
use std::cmp::Ordering;
fn cmp(a: int, b: int) -> Ordering {
if a < b { Ordering::Less }
else if a > b { Ordering::Greater }

View File

@ -467,6 +467,7 @@ fn free_handle(handle: *mut ()) {
#[cfg(test)]
mod tests {
use c_str::ToCStr;
#[test]
fn test_make_command_line() {

View File

@ -10,7 +10,7 @@
// Basic boolean tests
use std::cmp::{Equal, Greater, Less};
use std::cmp::Ordering::{Equal, Greater, Less};
use std::ops::{BitAnd, BitOr, BitXor};
fn main() {

View File

@ -17,22 +17,23 @@
extern crate log;
extern crate libc;
use std::comm::channel;
use std::io::net::tcp::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};
use std::thread::Builder;
use std::thread::{Builder, Thread};
use std::time::Duration;
fn main() {
// This test has a chance to time out, try to not let it time out
spawn(move|| {
Thread::spawn(move|| -> () {
use std::io::timer;
timer::sleep(Duration::milliseconds(30 * 1000));
println!("timed out!");
unsafe { libc::exit(1) }
});
}).detach();
let (tx, rx) = channel();
spawn(move|| {
Thread::spawn(move || -> () {
let mut listener = TcpListener::bind("127.0.0.1:0").unwrap();
tx.send(listener.socket_name().unwrap());
let mut acceptor = listener.listen();
@ -47,7 +48,7 @@ fn main() {
stream.read_byte();
stream.write(&[2]);
}
});
}).detach();
let addr = rx.recv();
let (tx, rx) = channel();