Rust Module Essentials
Tags: rust, module, examples, howto
Published: 2017-12-19 04:35:11

---
title: Rust Module Essentials
published: true
description: A tour of an important Rust feature, with lots of examples.
tags: Rust, module, examples, howto
---
Do you remember the first time you made a project with more than one source file? Was it with headers, with classes...or, with modules?

Modules have certain traits. They allow various items to coexist in a unit, without being bound to a class. A module file generally has its interface (outward-facing public parts) on top, and its implementation (dirty inner details) on the bottom.

Understanding Rust's modules comes from understanding the keywords `mod`, `pub`, and `use`. To state them simply:
 - `mod` declares a module.
 - `pub` exposes.
 - `use` pulls things in.

Let's begin with an example. Modules can be defined two ways. First in place:
```rust
// main.rs

mod food {
    pub fn eat() {
        println!("Good.");
    }
}
fn main() {
    food::eat();
}
```
Second, as a separate file:
```rust
// main.rs

mod food;

fn main() {
    food::eat();
}

// food.rs or food/mod.rs

pub fn eat() {
    println!("Yum.");
}
```
So more specifically:
>`mod X` means: let there be a module X, defined either here, in braces, or in a separate file named `X.rs` or `X/mod.rs`.

`pub fn eat` makes `eat` visible to main. Without `pub`, main would not be able to call `eat`.

Note that without `mod food` in main, Rust would ignore `food.rs` entirely.

Next, let's expand the above to something more deeply nested:
```rust
// main.rs

mod food {
    pub mod lunch {
        pub fn eat() {
             println!("Take a break.");
        }
    }
}
fn main() {
    food::lunch::eat();
}
```
Or, as multiple files. Note the use of `mod.rs`, a special filename:
```rust
// main.rs

mod food;

fn main() {
    food::lunch::eat();
}

// food/mod.rs

pub mod lunch;

// food/lunch.rs

pub fn eat() {
    println!("Hamburger.");
}
```
Does this look like you expected? Notice how both `fn eat` and `mod lunch` are made `pub`. They must be carried up this way, one level at a time.

And of course, anything without `pub` is invisible outside its module.

Perhaps surprisingly, `pub` treats struct members and methods on an individual basis.
```rust
// food.rs

struct Meal {
    pub taste: String,
    price: u32, // cannot see price
}

impl Meal {
    pub fn eat(&self) {
        println!("I taste {}.", self.taste);
    }
    fn purchase(&self) { // cannot call purchase directly
        println!("Spent ${}. Ouch.", self.price);
    }
}
```
Having a private variable `price` means that you cannot make a `Meal` outside of `food`. A constructor method can help with that.
```rust
// food.rs

impl Meal {
    pub fn fancy() -> Self {
        Meal {
            taste: String::from("miracles on plate"),
            price: 44100,
        }
    }
}

// main.rs

mod food;

fn main() {
    let lunch = food::Meal::fancy();
    lunch.eat();
}
```
So, to recap:
>`pub` exposes an item, either on module or struct level, to its surrounding level.

Do note that `Meal::fancy` could also be named `Meal::new`, or even other things.

Next, let's examine `use` to complete our set of three. `use` is a tool that pulls in words to reduce visual clutter and finger work.
```rust
mod food;
use food::Meal;

fn main() {
    let lunch = Meal::fancy();
    lunch.eat();
}
```
Or even:
```rust
mod food;
use food::Meal::fancy;

fn main() {
    let lunch = fancy();
    lunch.eat();
}
```
Pulling in `fancy` directly is an extreme example, but it does work. In the same way that `pub` can apply to structs, so can `use`.

A wrinkle with `use` is that it has absolute paths. To understand paths, consider this non-working example:
```rust
mod food {
    fn cheaper(a: &Meal, b: &Meal) -> u32 {
        std::cmp::min(a.price, b.price)
    }
}

```
This fails because `std::cmp` is the same as writing `self::std::cmp`, `self` here being `food`. It's a relative path. So, let's use an absolute path by adding `::` to the start.
```rust
mod food {
    fn cheaper(a: &Meal, b: &Meal) -> u32 {
        ::std::cmp::min(a.price, b.price)
    }
}
```
This works, but the `use` keyword is also an absolute path, and can reduce typing in the long run.
```rust 
mod food {
    use std;
    fn cheaper(a: &Meal, b: &Meal) -> u32 {
        std::cmp::min(a.cost, b.cost)
    }
}
```
Here's another way of doing it. Yes, `use` does respect its scope.
```rust
mod food {
    fn cheaper(a: &Meal, b: &Meal) -> u32 {
        use std::cmp::min;
        min(a.cost, b.cost)
    }
}
```

There is some light alternate syntax for `use` as well, in order to pull in multiple things.
```rust
mod food {
   pub mod bread {
       pub struct Slice {}
       pub struct Loaf {}
   }
   pub struct Plate {}
   pub struct Napkin {}
}

use food::bread::*; // pulls in Slice and Loaf
use food::{Plate, Napkin};
```
So, to be specific:
>`use` brings module or struct items into the current scope from an absolute path.

Also note that `pub use` can be used as a flattening method.
```rust
mod food {
    pub mod breakfast {
        pub mod cereal {
            pub fn eat() {
                println!("Snip, crankle, porp.");
            }
        }
    }
    pub use self::breakfast::cereal;
}
fn main() {
    food::cereal::eat();
}
```
This enables you to divide into further modules for organization, without adding a burden to the outside world.

Overall, it is better to be more explicit (avoid too much `*`) and `use` judiciously. It's better to know where things are coming from when you see them later, but added visual clutter and typing are no fun.

To recap:
 - `mod` declares a module.
 - `pub` exposes an item by a single level.
 - `use` brings things from an absolute path to the current scope.

There is more, but I hope I have helped get things started. Let me know if you're interested in a second part.