24 days from Node.js to Rust

preface

One of the outstanding features of Node.js when it was first released was how easy it was to use. To run a JavaScript file, just use the Node file.js command, and to import a native module, just (“./module.js”). If require() is not a relative or absolute path, then node will look in the node_modules folder. That was the good old days, of course, and if you’ve been around Node.js for a few years now, you might have a different idea of how easy it is. But in the beginning, it was really easy.

Rust’s modular system is subtly different from JavaScript’s, and it’s certainly not difficult to master, but until you do, you’re often surprised

The body of the

How do I import files?

The most straightforward answer is: you don’t need to import files. You don’t need import files in Rust. You just declare the module, and when you declare a module without the body, Rust automatically looks up the module in the file system based on its algorithm, which is highly dependent on the project file directory structure

Declare modules with the mod keyword, if you write mod my_module; , Rust will automatically search for files named my_module.rs and query for modules of my_module

There is no node relative file path relationship

Reference: see how to split modules into different files

How do I import functions from other modules

The use statement can place the contents of other modules in the current scope so that they can be used directly. This mechanism is the same for external dependencies and local modules, such as:

some_module::some_function();

/ / equivalent to the
use some_module::some_function;
some_function()
Copy the code

You can use {} to introduce more than one thing:

use std::io::{Read, Write};
Copy the code

Reference the contents of the parent module with super:

fn work() {}

mod test {
	use super::work;
}
Copy the code

Crate references the contents of the crate root:

use crate::some_module::some_function
Copy the code

Important concepts

Crate and crate

A Rust project is a Crate, and crate root refers to the original source file compiled by the Rust compiler. In Node.js it is usually index.js, which is configured via “main” in package.json. In Rust, crate root for a standalone executable is main.rs and Crate root for a code base is lib.rs, which is configured through Cargo

Crate root specifies the root path for Rust to search for imported modules

module

If you know from the beginning that Rust modules have nothing to do with file names or paths, the rest is easy. You may see different statements in documentation and other projects, but these statements are also false, and module is just a concept inherent in Rust

A Module is a namespace, where you group similar code together. A Module controls the visibility of such code, such as public or private. There can be many modules in a file, and modules can be nested:

fn main() {
  my_module::print(my_module::submodule::MSG);
}

mod my_module {
  pub fn print(msg: &str) {
    println!("{}", msg);
  }
  pub mod submodule {
    pub const MSG: &str = "Hello world!"; }}Copy the code

When you structure your code, you want it to be placed logically in separate files. Rust supports automatic query of modules in your local file system

Suppose we want to put my_module in another file, we create a my_module.rs file, copy the code in it, and leave the mod my_module empty in main.rs. :

// src/main.rs

fn main() {
  my_module::print(my_module::submodule::MSG);
}

mod my_module;


// src/my_module.rs

pub fn print(msg: &str) {
  println!("{}", msg);
}

pub mod submodule {
  pub const MSG: &str = "Hello world!";
}
Copy the code

Main.js declares a module named my_module, but its contents are empty, so Rust needs to find its definition

File query algorithm

  1. Start with the same path as the current module, for example if you are incrate root, then the path is. /. If it is inone::two::threeIn the module, the start is./one/two/three
  2. Query and import files with the same name as the module, for examplemod my_moduleWill automatically querymy_module.rsfile
  3. Will be queried in the folder of the imported module namemod.rsFiles, such asmy_module/mod.rs
  4. If you have zero matches or more matches it can complicate things

Note: The mod.rs form is a technical legacy, and similar uses may still be seen in some projects, but are no longer recommended

This means that in a well-organized project, its modules are a mirror image of the relative paths of the file system. Take a look at this code:


// src/mian.rs

fn main() {}

mod module_a;
mod one {
  mod two {
    modmodule_b; }}Copy the code

Mod Module_A and Mod Module_B are declared in the same file, so where does Rust look?

Will look for Module_A in./ module_A. Rs or./ module_A /mod.rs

Module_b will be found in./one/two/ module_B. Rs or./one/two/ Module_B /mod.rs

visibility

By default, all traits (except trait methods and enumeration variants) are private, but visibility only acts as a barrier to modules that can be accessed freely within the same module

Content defined at the upper level is invisible to deeper content by default, unless pub is used to change visibility. You can use modifiers on pub to adjust visibility, for example:

  • pub(crate): For the samecrateIs visible
  • pub(super): Visible only to the parent module

There are other modifiers, but they are less common, as listed in the reference article below

Modification of the Light example

The previous Light project has become quite large and it is time to refactor by file partition. This is an example of refactoring

Refer to the article

  • The Rust Book: ch 7
  • Rust by Example: Modules
  • Rust by Example: Crates
  • The Rust Reference: Modules

conclusion

Mod is not import, and once you’ve overcome this misconception, you’ll understand the module system, and in the next article we’ll pick up where String left off

More and more

  • Rust tutorial (1) From NVM to Rust
  • Rust tutorial (2) from NPM to Cargo for the front end
  • Configure Visual Studio Code in Rust (3)
  • Rust tutorial (4) Hello World
  • Rust Tutorial for the front end (5) Borrowing & Ownership
  • Part 1 of Rust Tutorial (6) String
  • Rust Tutorial (7)
  • Rust Tutorial (8)
  • Rust Tutorial (9)
  • Rust tutorial for the front end (10) from Mixins to Traits
  • Rust Tutorial (11) Module for the front-end
  • Part 2 of Rust Tutorial (12) String
  • Rust Tutorial (13) Results & Options