Skip to content

Instantly share code, notes, and snippets.

@gwuah
Last active April 29, 2022 10:19
Show Gist options
  • Save gwuah/5d73e3c35824d0789fcf3d7ba6c8a50a to your computer and use it in GitHub Desktop.
Save gwuah/5d73e3c35824d0789fcf3d7ba6c8a50a to your computer and use it in GitHub Desktop.

Rust Module System

The rust compiler makes little/no assumptions about the structure of your project. You’re required to construct your entire module tree yourself. To make our work easy, it provides us with some building blocks for this construction

The rust module systems works similar to modern filesystems. There’s a parent & some children. That said, rust has a unique way of doing everything you already know, so I’ll advice you approach this note on a blank state and try to draw parallels later.

The entry-point of modules in rust terminology is called a crate root. A crate root can either be 2 things, src/main.rs or src/lib.rs. A src/main.rs is called a binary crate root. A src/lib.rs is called a library crate root.

src
└lib.rs 
src
└main.rs

When you pass a rust project with this structure to the compiler, the only thing it sees is “crate”. That is, src/main.rs -> crate & src/lib.rs -> crate.

For this note, I’m going to build my module tree on the src/lib.rs base. To create a library crate, run cargo new --lib africa in your terminal.

Now to define a module, we use the mod keyword. A few notes on this keyword.

  • mod creates a scope/boundary for your module
  • mod can search for a file, read the content of the file and create a scope around it.
  • contents of mod are private by default, so we use the "pub" keyword to make them public.
mod Country {}
  • This creates a module called country. The scope/boundary of Country is demarcated by the “{“ and “}”.
  • Everything defined within the curly braces falls under the boundary of Country. Just like how borders work.

Let's represent africa using rust's module sytem.

Inside src/lib.rs, let's place this code.

mod countries {
    mod ghana {
        fn accra() {
            println!("capital of ghana")
        }
    }

    mod nigeria {
        fn lagos() {
            println!("capital of nigeria")
        }
    }
}

Even though our project looks like this

└─ src
   └─ lib.rs

This is what the rust compiler actually sees

└─ crate
   └─ countries

Where's everything else? Hidden. Hidden in the countries scope. To make them public, use the pub keyword. Note that, items within a scope can see what's around them (without needing the pub keyword)

mod countries {
    pub mod ghana {
        pub fn accra() {
            println!("capital of ghana")
        }
    }

    pub mod nigeria {
        pub fn lagos() {
            println!("capital of nigeria")
        }
    }
}

Now that we've made the children public, this is how the compiler sees our module tree.

└─ crate
   └─ countries
      ├─ ghana
      │  └─ accra
      └─ nigeria
         └─ lagos

If this were your file system using the absolute path, you'll access it this way. ~/crate/countries/ghana or ~/crate/countries/nigeria

It's no different in rust, this is how you'll acess these modules using absolute path. crate::countries::ghana or crate::countries::nigeria

Absolute paths are great, but verbose. what if we wanted to use relative paths. If someone in accra wants to communicate with someone in lagos, they can use either 1 of these addresses.

From accra, absolute address to lagos

  • filesystem path - ~/crate/countries/nigeria/lagos
  • rust module path - crate::countries::nigeria::lagos

From accra, relative address to lagos

  • filesystem path - ../nigeria/lagos
  • rust module path - super::nigeria::lagos

The super keyword is used to refers to the parent of a module. In ghana(accra), super refers to countries. In nigeria(lagos), super refers to countries.

There's also the self keyword, which refers to the module itself. In ghana(accra), self refers to ghana. In nigeria(lagos), self refers to nigeria.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment