Skip to content

Commit

Permalink
Properly deal with Ordering in the guide
Browse files Browse the repository at this point in the history
Now that it's been removed from the prelude, we need to treat things differently.

Fixes #17967
  • Loading branch information
steveklabnik authored and alexcrichton committed Jan 2, 2015
1 parent 56290a0 commit 76e3bc2
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 40 deletions.
82 changes: 48 additions & 34 deletions src/doc/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand All @@ -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.

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.
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`.

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.
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.

This enum has two variants, one of which has a value:

Expand Down Expand Up @@ -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())
Expand All @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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 }
Expand All @@ -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 }
Expand Down Expand Up @@ -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 }
Expand Down
1 change: 1 addition & 0 deletions src/libstd/sys/windows/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,7 @@ fn free_handle(handle: *mut ()) {

#[cfg(test)]
mod tests {
use c_str::ToCStr;

#[test]
fn test_make_command_line() {
Expand Down
2 changes: 1 addition & 1 deletion src/test/run-pass/bool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
11 changes: 6 additions & 5 deletions src/test/run-pass/tcp-stress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -47,7 +48,7 @@ fn main() {
stream.read_byte();
stream.write(&[2]);
}
});
}).detach();
let addr = rx.recv();

let (tx, rx) = channel();
Expand Down

3 comments on commit 76e3bc2

@bors
Copy link
Contributor

@bors bors commented on 76e3bc2 Jan 2, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from aturon
at alexcrichton@76e3bc2

@bors
Copy link
Contributor

@bors bors commented on 76e3bc2 Jan 2, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging alexcrichton/rust/issue-20068 = 76e3bc2 into auto

@bors
Copy link
Contributor

@bors bors commented on 76e3bc2 Jan 2, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging alexcrichton/rust/issue-20068 = 76e3bc2 into auto failed

Please sign in to comment.