Skip to content

Commit

Permalink
book: some Crates and Modules nits
Browse files Browse the repository at this point in the history
  • Loading branch information
tshepang committed Mar 22, 2015
1 parent 542e2bb commit 8a500de
Showing 1 changed file with 24 additions and 76 deletions.
100 changes: 24 additions & 76 deletions src/doc/trpl/crates-and-modules.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
% Crates and Modules

When a project starts getting large, it's considered a good software
When a project starts getting large, it's considered good software
engineering practice to split it up into a bunch of smaller pieces, and then
fit them together. It's also important to have a well-defined interface, so
that some of your functionality is private, and some is public. To facilitate
Expand All @@ -24,23 +24,23 @@ in different languages. To keep things simple, we'll stick to "greetings" and
two languages for those phrases to be in. We'll use this module layout:

```text
+-----------+
+---| greetings |
| +-----------+
+---------+ |
| english |---+
+---------+ | +-----------+
| +---| farewells |
+---------+ | +-----------+
+-----------+
+---| greetings |
| +-----------+
+---------+ |
+---| english |---+
| +---------+ | +-----------+
| +---| farewells |
+---------+ | +-----------+
| phrases |---+
+---------+ | +-----------+
| +---| greetings |
+----------+ | +-----------+
| japanese |---+
+----------+ |
| +-----------+
+---| farewells |
+-----------+
+---------+ | +-----------+
| +---| greetings |
| +----------+ | +-----------+
+---| japanese |--+
+----------+ |
| +-----------+
+---| farewells |
+-----------+
```

In this example, `phrases` is the name of our crate. All of the rest are
Expand Down Expand Up @@ -76,25 +76,19 @@ To define each of our modules, we use the `mod` keyword. Let's make our
`src/lib.rs` look like this:

```
// in src/lib.rs
mod english {
mod greetings {
}
mod farewells {
}
}
mod japanese {
mod greetings {
}
mod farewells {
}
}
```
Expand Down Expand Up @@ -145,11 +139,7 @@ mod english;
```

If we do that, Rust will expect to find either a `english.rs` file, or a
`english/mod.rs` file with the contents of our module:

```{rust,ignore}
// contents of our module go here
```
`english/mod.rs` file with the contents of our module.

Note that in these files, you don't need to re-declare the module: that's
already been done with the initial `mod` declaration.
Expand Down Expand Up @@ -181,10 +171,7 @@ $ tree .
`src/lib.rs` is our crate root, and looks like this:

```{rust,ignore}
// in src/lib.rs
mod english;
mod japanese;
```

Expand All @@ -195,10 +182,7 @@ chosen the second. Both `src/english/mod.rs` and `src/japanese/mod.rs` look
like this:

```{rust,ignore}
// both src/english/mod.rs and src/japanese/mod.rs
mod greetings;
mod farewells;
```

Expand All @@ -214,8 +198,6 @@ both empty at the moment. Let's add some functions.
Put this in `src/english/greetings.rs`:

```rust
// in src/english/greetings.rs

fn hello() -> String {
"Hello!".to_string()
}
Expand All @@ -224,8 +206,6 @@ fn hello() -> String {
Put this in `src/english/farewells.rs`:

```rust
// in src/english/farewells.rs

fn goodbye() -> String {
"Goodbye.".to_string()
}
Expand All @@ -248,8 +228,6 @@ about the module system.
Put this in `src/japanese/farewells.rs`:

```rust
// in src/japanese/farewells.rs

fn goodbye() -> String {
"さようなら".to_string()
}
Expand All @@ -265,11 +243,9 @@ another crate.
We have a library crate. Let's make an executable crate that imports and uses
our library.

Make a `src/main.rs` and put this in it: (it won't quite compile yet)
Make a `src/main.rs` and put this in it (it won't quite compile yet):

```rust,ignore
// in src/main.rs
extern crate phrases;
fn main() {
Expand Down Expand Up @@ -320,8 +296,6 @@ keyword. Let's focus on the `english` module first, so let's reduce our `src/mai
to just this:
```{rust,ignore}
// in src/main.rs
extern crate phrases;
fn main() {
Expand All @@ -333,28 +307,20 @@ fn main() {
In our `src/lib.rs`, let's add `pub` to the `english` module declaration:
```{rust,ignore}
// in src/lib.rs

pub mod english;

mod japanese;
```
And in our `src/english/mod.rs`, let's make both `pub`:
```{rust,ignore}
// in src/english/mod.rs
pub mod greetings;
pub mod farewells;
```
In our `src/english/greetings.rs`, let's add `pub` to our `fn` declaration:
```{rust,ignore}
// in src/english/greetings.rs

pub fn hello() -> String {
"Hello!".to_string()
}
Expand All @@ -363,8 +329,6 @@ pub fn hello() -> String {
And also in `src/english/farewells.rs`:
```{rust,ignore}
// in src/english/farewells.rs

pub fn goodbye() -> String {
"Goodbye.".to_string()
}
Expand Down Expand Up @@ -400,8 +364,6 @@ Rust has a `use` keyword, which allows us to import names into our local scope.
Let's change our `src/main.rs` to look like this:
```{rust,ignore}
// in src/main.rs

extern crate phrases;

use phrases::english::greetings;
Expand Down Expand Up @@ -430,7 +392,7 @@ fn main() {
}
```
But it is not idiomatic. This is significantly more likely to introducing a
But it is not idiomatic: it is more likely to introduce a
naming conflict. In our short program, it's not a big deal, but as it grows, it
becomes a problem. If we have conflicting names, Rust will give a compilation
error. For example, if we made the `japanese` functions public, and tried to do
Expand Down Expand Up @@ -460,21 +422,19 @@ Could not compile `phrases`.
```
If we're importing multiple names from the same module, we don't have to type it out
twice. Rust has a shortcut syntax for writing this:
twice. Instead of this:
```{rust,ignore}
use phrases::english::greetings;
use phrases::english::farewells;
```
You use curly braces:
We can use this shortcut:
```{rust,ignore}
use phrases::english::{greetings, farewells};
```
These two declarations are equivalent, but the second is a lot less typing.
## Re-exporting with `pub use`
You don't just use `use` to shorten identifiers. You can also use it inside of your crate
Expand All @@ -484,8 +444,6 @@ interface that may not directly map to your internal code organization.
Let's look at an example. Modify your `src/main.rs` to read like this:
```{rust,ignore}
// in src/main.rs
extern crate phrases;
use phrases::english::{greetings,farewells};
Expand All @@ -503,18 +461,13 @@ fn main() {
Then, modify your `src/lib.rs` to make the `japanese` mod public:
```{rust,ignore}
// in src/lib.rs
pub mod english;
pub mod japanese;
```
Next, make the two functions public, first in `src/japanese/greetings.rs`:
```{rust,ignore}
// in src/japanese/greetings.rs
pub fn hello() -> String {
"こんにちは".to_string()
}
Expand All @@ -523,8 +476,6 @@ pub fn hello() -> String {
And then in `src/japanese/farewells.rs`:
```{rust,ignore}
// in src/japanese/farewells.rs
pub fn goodbye() -> String {
"さようなら".to_string()
}
Expand All @@ -533,13 +484,10 @@ pub fn goodbye() -> String {
Finally, modify your `src/japanese/mod.rs` to read like this:
```{rust,ignore}
// in src/japanese/mod.rs
pub use self::greetings::hello;
pub use self::farewells::goodbye;
mod greetings;
mod farewells;
```
Expand All @@ -551,9 +499,9 @@ module, we now have a `phrases::japanese::hello()` function and a
`phrases::japanese::farewells::goodbye()`. Our internal organization doesn't
define our external interface.
Here we have a `pub use` for each function we want to bring into the
Here we have a `pub use` for each function we want to bring into the
`japanese` scope. We could alternatively use the wildcard syntax to include
everything from `greetings` into the current scope: `pub use self::greetings::*`.
everything from `greetings` into the current scope: `pub use self::greetings::*`.
What about the `self`? Well, by default, `use` declarations are absolute paths,
starting from your crate root. `self` makes that path relative to your current
Expand Down

0 comments on commit 8a500de

Please sign in to comment.