提交 76e3bc23 编写于 作者: S Steve Klabnik 提交者: Alex Crichton

Properly deal with Ordering in the guide

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

Fixes #17967
上级 56290a00
...@@ -1106,10 +1106,17 @@ enum Ordering { ...@@ -1106,10 +1106,17 @@ enum Ordering {
``` ```
An `Ordering` can only be _one_ of `Less`, `Equal`, or `Greater` at any given 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} ```{rust}
# use std::cmp::Ordering; use std::cmp::Ordering;
fn cmp(a: int, b: int) -> Ordering { fn cmp(a: int, b: int) -> Ordering {
if a < b { Ordering::Less } if a < b { Ordering::Less }
else if a > b { Ordering::Greater } else if a > b { Ordering::Greater }
...@@ -1132,18 +1139,25 @@ fn main() { ...@@ -1132,18 +1139,25 @@ fn main() {
} }
``` ```
`cmp` is a function that compares two things, and returns an `Ordering`. We There's a symbol here we haven't seen before: the double colon (`::`).
return either `Less`, `Greater`, or `Equal`, depending on if the two values This is used to indicate a namesapce. In this case, `Ordering` lives in
are greater, less, or equal. 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.
The `ordering` variable has the type `Ordering`, and so contains one of the Okay, let's talk about the actual code in the example. `cmp` is a function that
three values. We can then do a bunch of `if`/`else` comparisons to check compares two things, and returns an `Ordering`. We return either
which one it is. `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`.
However, repeated `if`/`else` comparisons get quite tedious. Rust has a feature The `ordering` variable has the type `Ordering`, and so contains one of the
that not only makes them nicer to read, but also makes sure that you never three values. We can then do a bunch of `if`/`else` comparisons to check which
miss a case. Before we get to that, though, let's talk about another kind of one it is. However, repeated `if`/`else` comparisons get quite tedious. Rust
enum: one with values. 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: This enum has two variants, one of which has a value:
...@@ -1176,18 +1190,19 @@ enum StringResult { ...@@ -1176,18 +1190,19 @@ enum StringResult {
ErrorReason(String), ErrorReason(String),
} }
``` ```
Where a `StringResult` is either a `StringOK`, with the result of a computation, or an Where a `StringResult` is either a `StringResult::StringOK`, with the result of
`ErrorReason` with a `String` explaining what caused the computation to fail. These kinds of a computation, or an `StringResult::ErrorReason` with a `String` explaining
`enum`s are actually very useful and are even part of the standard library. 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 Here is an example of using our `StringResult`:
our `StringResult`:
```rust ```rust
# enum StringResult { enum StringResult {
# StringOK(String), StringOK(String),
# ErrorReason(String), ErrorReason(String),
# } }
fn respond(greeting: &str) -> StringResult { fn respond(greeting: &str) -> StringResult {
if greeting == "Hello" { if greeting == "Hello" {
StringResult::StringOK("Good morning!".to_string()) StringResult::StringOK("Good morning!".to_string())
...@@ -1197,10 +1212,7 @@ fn respond(greeting: &str) -> StringResult { ...@@ -1197,10 +1212,7 @@ fn respond(greeting: &str) -> StringResult {
} }
``` ```
Notice that we need both the enum name and the variant name: `StringResult::StringOK`, but That's a lot of typing! We can use the `use` keyword to make it shorter:
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`:
```rust ```rust
use StringResult::StringOK; use StringResult::StringOK;
...@@ -1222,12 +1234,11 @@ fn respond(greeting: &str) -> StringResult { ...@@ -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 `use` declarations must come before anything else, which looks a little strange in this example,
must come before anything else, which looks a little strange in this example, since we `use` since we `use` the variants before we define them. Anyway, in the body of `respond`, we can just
the variants before we define them. Anyway, in the body of `respond`, we can just say `StringOK` say `StringOK` now, rather than the full `StringResult::StringOK`. Importing variants can be
now, rather than the full `StringResult::StringOK`. Importing variants can be convenient, but can convenient, but can also cause name conflicts, so do this with caution. It's considered good style
also cause name conflicts, so do this with caution. It's considered good style to rarely import to rarely import variants for this reason.
variants for this reason.
As you can see, `enum`s with values are quite a powerful tool for data representation, 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, 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. ...@@ -1281,7 +1292,8 @@ for every possible value of `x`, and so our program will compile successfully.
section on enums? section on enums?
```{rust} ```{rust}
# use std::cmp::Ordering; use std::cmp::Ordering;
fn cmp(a: int, b: int) -> Ordering { fn cmp(a: int, b: int) -> Ordering {
if a < b { Ordering::Less } if a < b { Ordering::Less }
else if a > b { Ordering::Greater } else if a > b { Ordering::Greater }
...@@ -1307,7 +1319,8 @@ fn main() { ...@@ -1307,7 +1319,8 @@ fn main() {
We can re-write this as a `match`: We can re-write this as a `match`:
```{rust} ```{rust}
# use std::cmp::Ordering; use std::cmp::Ordering;
fn cmp(a: int, b: int) -> Ordering { fn cmp(a: int, b: int) -> Ordering {
if a < b { Ordering::Less } if a < b { Ordering::Less }
else if a > b { Ordering::Greater } else if a > b { Ordering::Greater }
...@@ -1368,7 +1381,8 @@ side of a `let` binding or directly where an expression is used. We could ...@@ -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: also implement the previous line like this:
```{rust} ```{rust}
# use std::cmp::Ordering; use std::cmp::Ordering;
fn cmp(a: int, b: int) -> Ordering { fn cmp(a: int, b: int) -> Ordering {
if a < b { Ordering::Less } if a < b { Ordering::Less }
else if a > b { Ordering::Greater } else if a > b { Ordering::Greater }
......
...@@ -467,6 +467,7 @@ fn free_handle(handle: *mut ()) { ...@@ -467,6 +467,7 @@ fn free_handle(handle: *mut ()) {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use c_str::ToCStr;
#[test] #[test]
fn test_make_command_line() { fn test_make_command_line() {
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
// Basic boolean tests // Basic boolean tests
use std::cmp::{Equal, Greater, Less}; use std::cmp::Ordering::{Equal, Greater, Less};
use std::ops::{BitAnd, BitOr, BitXor}; use std::ops::{BitAnd, BitOr, BitXor};
fn main() { fn main() {
......
...@@ -17,22 +17,23 @@ ...@@ -17,22 +17,23 @@
extern crate log; extern crate log;
extern crate libc; extern crate libc;
use std::comm::channel;
use std::io::net::tcp::{TcpListener, TcpStream}; use std::io::net::tcp::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener}; use std::io::{Acceptor, Listener};
use std::thread::Builder; use std::thread::{Builder, Thread};
use std::time::Duration; use std::time::Duration;
fn main() { fn main() {
// This test has a chance to time out, try to not let it time out // This test has a chance to time out, try to not let it time out
spawn(move|| { Thread::spawn(move|| -> () {
use std::io::timer; use std::io::timer;
timer::sleep(Duration::milliseconds(30 * 1000)); timer::sleep(Duration::milliseconds(30 * 1000));
println!("timed out!"); println!("timed out!");
unsafe { libc::exit(1) } unsafe { libc::exit(1) }
}); }).detach();
let (tx, rx) = channel(); let (tx, rx) = channel();
spawn(move|| { Thread::spawn(move || -> () {
let mut listener = TcpListener::bind("127.0.0.1:0").unwrap(); let mut listener = TcpListener::bind("127.0.0.1:0").unwrap();
tx.send(listener.socket_name().unwrap()); tx.send(listener.socket_name().unwrap());
let mut acceptor = listener.listen(); let mut acceptor = listener.listen();
...@@ -47,7 +48,7 @@ fn main() { ...@@ -47,7 +48,7 @@ fn main() {
stream.read_byte(); stream.read_byte();
stream.write(&[2]); stream.write(&[2]);
} }
}); }).detach();
let addr = rx.recv(); let addr = rx.recv();
let (tx, rx) = channel(); let (tx, rx) = channel();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册