Unlike other programming languages, a module do not represent a file. It represents something else. It is very similar to a "namespace". One source file *.rs can define many modules.
Each module can contain other modules inside. This will create a hierarchy. You can use two columns "::" as delimiter to identify a module component similar to URL that is using "/" as delimiter.
Example: module::sub-module::component-name
You can use "pub" keyword to define public modules. This indicate that a module member can be used outside of module scope. You can use "*" to import all "pub" members defined into a module or you can specify each member to be imported by name. After import you can use the members as part of current scope.
In this example modules are defined in a single file:
pub mod first_module {
pub mod sub_module {
pub fn test() {
println!("You found me again");
}
} //end sub_module
pub fn test() {
println!("You found me");
}
} // end first_module
// import in current namespace all elements of first_module
use first_module::*;
fn main() {
test(); // You found me
sub_module::test(); // You found me again
}
Notes:
Homework: This example can be tested live: modules
In Rust, a crate is a binary or library that can be compiled and executed. A crate can contain one or more modules, and each module can be nested within other modules.
A crate begins with a root module, which is defined in a file with the same name as the crate. All other modules in the crate can then be organized hierarchically under the root module.
For example, suppose we have a crate named "my_crate". We can define the root module in a file named "main.rs" or "lib.rs", and then define other modules that belong to this crate like this:
// main.rs or lib.rs
mod my_module {
// module code
}
mod another_module {
// module code
}
In this example, our crate has two modules: "my_module" and "another_module", both of which are defined within the root module of the crate. Each module can then contain functions, structs, enums, and other modules.
We can also define modules that belong to a specific file in the crate. This is useful for organizing code that is related to a specific functionality:
// my_module.rs
pub mod sub_module {
// module code
}
In this example, we define a module named "sub_module" that belongs to the "my_module" module. The "pub" keyword makes this module accessible to code outside of the "my_module" module.
In summary, crates are the top-level organizational unit in Rust programs, while modules are used to organize code within a crate. Each crate can contain one or more modules, which can be nested within other modules to organize the code hierarchically.
In Rust, modules are an important feature that allows you to organize your code into logical groups. Each module can hold code related to a specific functionality, making it easier to navigate and understand a codebase. Here are some important things to know about modules in Rust:
pub
and mod
keywords.pub
keyword.foo.rs
can define a module named foo
that is a child of the root module.Modules are an important feature in Rust, but they're not strictly required. You can write all your code in a single file if you want to, but as your code grows in complexity, it will become harder to maintain and understand without proper organization. Modules provide a way to divide your code into smaller, more manageable pieces, making it easier to reason about and maintain over time.
In Rust, modules don't have versions on their own. Versioning is mainly used to manage dependencies between different modules or crates, which are collections of modules.
Each crate has a version listed in its "Cargo.toml" manifest file. When you specify a dependency on a crate in your own "Cargo.toml", you can require a specific version or version range of that crate.
For example, suppose your crate depends on "serde", a popular Rust library for serializing and deserializing data. You could specify a specific version of "serde", like this:
[dependencies] serde = "1.0.104"
Or, you could specify a version range, like this:
[dependencies] serde = "^1.0.104"
The caret ("^") character means that your crate can use any version of "serde" that is compatible with version 1.0.104, but not any major version that might break compatibility.
To update a crate's version, you can manually change the version in "Cargo.toml" and then run "cargo update". Alternatively, you can automatically update all dependencies to their latest compatible versions by running "cargo update --aggressive".
Rust's package manager, Cargo, automatically resolves and downloads the versions of crates specified in your "Cargo.toml" file, as well as any dependencies those crates may have. This helps ensure that your project uses compatible and up-to-date versions of all the dependencies it needs.
In Rust language, cargo
is the default package manager and build tool. It is used for managing dependencies and building, testing, and packaging Rust code.
The cargo
tool creates, builds and manages Rust projects. It also helps you automate tasks frequently required when building Rust software such as compiling source code, downloading and compiling various dependent libraries, running tests, and creating distributable packages.
To use Cargo, you need to have Rust installed on your system. Once you have Rust installed, you can use the cargo
command to create, build and manage your Rust projects.
Here are some common commands that you can use with Cargo:
cargo new project_name
- creates a new Rust project with the specified namecargo build
- builds the Rust projectcargo run
- builds and runs the Rust projectcargo test
- runs the tests in the Rust projectcargo doc
- builds the documentation for the Rust projectCargo also helps you manage dependencies by providing a simple and easy way of using external crates in your Rust project. You can specify your project's dependencies in the Cargo.toml
file that is created when you create a new Rust project using Cargo.
Here's an example Cargo.toml
file:
[package]
name = "my-app"
version = "0.1.0"
authors = ["Your Name <your-email@example.com>"]
edition = "2018"
[dependencies]
rand = "0.8.0"
In this example, we've specified a dependency on the rand
crate, version 0.8.0.
That's a brief overview of what cargo
is in Rust and how to use it. I hope that helps!
A ".toml" file is a configuration file format popularly used in Rust for specifying package metadata and configuration information. The name TOML stands for "Tom's Obvious, Minimal Language," created by Tom Preston-Werner in 2013. The syntax of TOML files is intended to be easy to read and parse by both humans and machines.
toml [package] name = "my_cool_project" version = "0.1.0" authors = ["Your Name yourname@example.com"] [dependencies] rand = "0.7.3"
In this example, we have two sections: "[package]" and "[dependencies]". The "package" section contains metadata about the package, such as its name, version, and author. The "dependencies" section lists the dependencies of the package, along with their versions.
The syntax of ".toml" files is based on key/value pairs. Sections are defined by enclosing their names in brackets ("[" and "]"). Within each section, the values are specified as "key = "value"" pairs. Values can be strings, integers, booleans, or arrays of any of these types. Comments in TOML files are started with the "#" character.
Rust uses ".toml" files for package metadata and configuration because they are easy to read and write, and they can be easily parsed by Rust's built-in "toml" crate. The "toml" crate allows Rust programs to read and write TOML files, making them a useful tool for Rust developers.
Read next: Errors