Why Rust?
I. Overview 🧐
A language empowering everyone to build reliable and efficient software.
Rust is one of the most widely used languages in blockchain systems and many popular blockchains including Solana, Polkadot, Aptos, and Sui are built with Rust. Rust frameworks such as Foundry are also highly preferred by developers of established chains including Ethereum.
The use of Rust is growing rapidly among blockchain projects, with more and more developers and teams recognizing the advantages of its performance and safety. In the coming years, we will see an exponential increase in this trend.
Rust is a modern programming language that has been gaining a reputation for its focus on safety and performance, making it worth learning for all developers!
II. Features ✨
1. Safety 🛡
Rust offers memory safety without the need for a garbage collector through its innovative ownership model.
Memory safety means that the language prevents bugs that lead to crashes or security vulnerabilities due to mishandled memory.
Rust's ownership model ensures that variables are deallocated when they go out of scope, preventing memory leaks and dangling references.
Additionally, Rust's borrow checker enforces strict rules around mutable and immutable references, preventing data races and other common concurrency bugs.
2. High Performance 🚀
Rust offers the speed of a compiled language and the efficiency of manual memory management without a garbage collector, making it an ideal candidate for performance-critical domains. Rust’s unique “zero-cost abstractions ” allow us to write code that is both high-performance and safe without experiencing additional runtime overhead.
Garbage collection involves the automated process of reclaiming memory that the runtime is no longer using. In simpler terms, it serves as a means to eliminate unused objects. The purpose of garbage collection is to prevent a program from exceeding its allocated memory capacity or reaching a state where it can no longer operate properly. Additionally, it relieves developers from the manual burden of managing a program’s memory, thereby reducing the potential for memory-related errors.
In contrast, Rust takes a distinct approach by forgoing the use of a garbage collector. Instead, it accomplishes these objectives through a sophisticated yet intricate type system. This methodology renders Rust exceptionally efficient; however, it also introduces a higher level of complexity to the learning and utilization of Rust.
3. Fearless Concurrency 🤝
Rust aims to make concurrent programming accessible and safe. It offers abstractions like threads and asynchronous programming while enforcing thread safety through the type system.
4. Ecosystem 🌍
Rust's ecosystem offers a treasure trove of libraries, tools, and frameworks.
The Cargo package manager simplifies dependency management, compilation, and building of Rust projects, fostering a vibrant ecosystem that continuously expands the language's applicability.
Furthermore, the integration with various languages through FFI (Foreign Function Interface) effectively bridges the gap between Rust's system-level efficiency and the user-friendly nature of high-level scripting languages.
Rust, while still growing, has an active community that continuously develops and maintains libraries (crates) for a wide range of use cases. You can find all sorts of libraries on crates.io.
5. Open Source Community 🧑🤝🧑
Rust has a very friendly and vibrant open-source developer community. This community is known for its enthusiasm, inclusivity, and willingness to help.
III. Hello World 🧑
1. Creating a New Project ➕
cargo new hello-rust
2. Project File Structure 📁
hello-rust/
├── Cargo.toml
├── .gitignore
└── src/
└── main.rs
-
Cargo.tomlis the core configuration file for Rust projects, used to define project metadata, dependencies, and build settings. -
.gitignorefile is used to specify which files and directories should be ignored by Git when tracking changes in a repository. -
src/main.rsis where we’ll write our application code.
3. Writing the Program ✍
fn main() {
println!("Hello World");
}
In Rust, every executable program must include a function named main as the entry point.
println!("Hello World");
This is a macro call used to output text to the standard output.
println! is one of the macros provided by Rust's standard library, which prints a line of text to the console and automatically adds a newline at the end. Unlike other languages where placeholders like %s or %d are used, println in Rust uses {}. This is because Rust does a lot of work under the hood to automatically recognize the type of the output data.
4. Running Code ▶️
cargo run
IV. Number Guessing Game 🔢
In this game, the computer randomly generates a number, and the player needs to guess what that number is. After each guess, the program will inform the player whether their guess is too high, too low, or correct. Through this process, the player can gradually narrow down the range until they find the correct number.
1. Input/Output 📥/📤
Enter a number and it will be displayed.
use std::io;
fn main() {
println!("Please input your guess:");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Failed to read line");
println!("You guessed: {}", guess);
}
use std::io;
This line imports the input/output module from Rust's standard library, allowing us to use input/output related functionalities.
fn main()
Defines the main function of the program, where the execution begins.
println!("Please input your guess:");
Uses the println! macro to print a prompt message to the console, asking the user to input their guess.
let mut guess = String::new();
Creates a mutable String type variable guess to store user input. The mut keyword indicates that this variable is mutable.
io::stdin()
Calls the stdin function from the io module, returning a handle to the standard input.
.read_line(&mut guess)
Calls the read_line method on the standard input handle to read a line of text from user input. &mut guess is a mutable reference, indicating that the user input will be stored in the guess variable.
.expect("Failed to read line");
The read_line method returns a Result type, and expect is used to handle potential errors. If reading fails, the program will terminate and display the specified error message.
println!("You guessed: {}", guess);
Uses the println! macro again to print the user's input. {} is a placeholder that will be replaced by the value of guess.
2. Randomly Generated 🎲
Generate a random number between 1 and 100.
[dependencies]
rand = "0.8.4"
use rand::Rng;
use std::io;
fn main() {
let secret_number = rand::thread_rng().gen_range(1..101);
println!("The secret number is: {}", secret_number);
println!("Please input your guess:");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Failed to read line");
println!("You guessed: {}", guess);
}
use rand:: Rng;
The rand::Rng package is a trait in Rust. You can think of a trait as an interface that defines certain methods that types must implement. When you bring a trait into your code using use, it’s similar to a class implementing an interface in other programming languages.
rand::thread_rng(): This function creates a random number generator that is local to the current thread. It is a convenient way to generate random numbers in a thread-safe manner.
.gen_range(1..101): This method generates a random number within the specified range. The range 1..101 means that the generated number will be between 1 and 100, inclusive of 1 and exclusive of 101.
let secret_number =: This part declares a new variable named secret_number and assigns it the value generated by the random number generator.
3. Compare ⚖
Compare the generated random number with the input number.
use rand::Rng;
use std::cmp::Ordering;
use std::io;
fn main() {
let secret_number = rand::thread_rng().gen_range(1..101);
// println!("The secret number is: {}", secret_number);
println!("Please input your guess:");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Failed to read line");
println!("You guessed: {}", guess);
let guess: u32 = guess.trim().parse().expect("Please type a number!");
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small"),
Ordering::Greater => println!("Too big"),
Ordering::Equal => println!("You win!"),
}
}
guess.trim() removes spaces, tabs, and carriage returns (pressing enter while typing results in \n input)
parse() will parse the input string, there are i32 u32 i64, we choose to parse it as u32.
.expect("Please type a number!"): This method is called on the result of the parse() method. If the parsing is successful, it returns the parsed number. If it fails (for example, if the input is not a valid number), it will panic and display the message "Please type a number!".
Ordering has three variants Less, Greater, Equal.
guess.cmp(&secret_number) is to compare guess with secret_number, this method returns an Ordering.
4. Final 🏁
Add loops until the rule is reached and then ends.
fn main() {
let secret_number = rand::thread_rng().gen_range(1..101);
// println!("The secret number is: {}", secret_number);
loop {
println!("Please input your guess:");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Failed to read line");
println!("You guessed: {}", guess);
let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small"),
Ordering::Greater => println!("Too big"),
Ordering::Equal => {
println!("You win!");
break;
}
}
}
}