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:
parent
56290a0044
commit
76e3bc2338
4 changed files with 56 additions and 40 deletions
|
@ -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 }
|
||||
|
|
|
@ -467,6 +467,7 @@ fn free_handle(handle: *mut ()) {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use c_str::ToCStr;
|
||||
|
||||
#[test]
|
||||
fn test_make_command_line() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Reference in a new issue