Learning Rust 101: My First Rust Program

Why Rust?

Rust is an exciting and unique programming language built to achieve the same level of control over memory and executing behavior as C++ combined with the comfort and expressiveness of a "guaranteed" safety high-level functional language with an incredible rich type system. One of its main pros is that it solves the dilemma of control versus safety, meaning that it does not sacrifice control over safety or vice versa(Yes, it is garbage collector free🀯). Rust is by no means perfect, and you should not use it in all scenarios, but when you need memory safety, efficiency, and speed, you should consider it.

The upsides of Rust:

  • Performance: No garbage collector and a compiler that does really good at optimizing both the size and speed of your program.

  • Cargo: A modern and friendly swiss-knife build system and package manager that builds, runs, test, documents, and publish your project.

  • Concurrency: Writing code that does more than one thing at a time is complex and challenging for programmers of all levels. Rust safety crosses the borders of independent threads without constraining thread speed.

The downsides of Rust:

  • Compile-time: Rust has a complex compiler toolchain. While the compiler is incredibly helpful, it is slower at compile time than other languages.

  • Strictness: Having guaranteed memory safety at compile time comes with a cost. You can NOT be lazy when writing Rust. Programs will not compile until everything is correct. This is helpful but can slow development and cause frustration. We will talk about ownership later, but to write Rust, you need to think Rust, which will take some time.

  • Learning curve: Rust is a complex language. It is not the easiest language to learn, and it introduces a lot of new concepts such as ownership, lifetimes, and borrowing.

The program

We will write a simple CLI program that calculates the weight of an object in other planets. The program will ask the user for their weight in kilograms and the planet they want to calculate the weight in. The program will then print the weight of the object in the selected planet.

The setup

First, we need to install Rust. You can do it by following the instructions in the official website. Once Rust is installed, we can create a new project by running the following command:

cargo new weight_on_planets

This will create a new folder called weight_on_planets with the following structure:

weight_on_planets
β”œβ”€β”€ Cargo.toml
└── src
    └── main.rs

The Cargo.toml file is the configuration file for our project. It contains the name of the project, the version, the authors, and the dependencies of the project. The src folder contains the source code of our project. The main.rs file is the entry point of our program.

The code

Let's start by writing the code that will ask the user for their weight and the planet they want to calculate the weight in. For this we first need to understand how to read input from the user and how to print to the console. Lets start by asking the user for their weight. We will use the println! macro to print a message to the console. The println! macro is similar to the console.log function in JavaScript. It takes a string as an argument and prints it to the console.

println!("What is your weight in kilograms?");

Voila! We just printed a message to the console.

The next step is to read the input from the user. We will use the read_line function from the standard library to read the input from the user. The read_line function takes a mutable string as an argument. A mutable string is a string that can be modified.

use std::io;

fn main() {
println!("What is your weight in kilograms?");
let mut weight = String::new();
std::io::stdin().read_line(&mut weight).unwrap();
println!("Your weight is: {}", weight);
}

Done! We just read the input from the user and printed it to the console. But what the heck is this &mut weight thing? The &mut weight is a reference to the weight variable. A reference is a pointer to a value. In this case, the reference points to the weight variable.

One of the most important concepts in Rust is ownership. Ownership is a concept that allows Rust to guarantee memory safety at compile time. When you create a variable in Rust, the variable is owned by the scope in which it was created. The scope is the part of the code where the variable is accessible. When the scope ends, the variable is dropped. This means that the variable is destroyed and the memory is freed.

This blog post is not about ownership, but here are the golden rules of ownership:

  • Each value in Rust is owned by a variable.
  • When the owner goes out of scope, the value is deallocated.
  • There can only be one owner at a time.

Back to our program. The next step is to collect the planet the user wants to calculate the weight in. We will use the same read_line function to read the input from the user.

use std::io;


fn main() {
println!("Which planet do you want to calculate your weight in?");
let mut planet_input = String::new();
io::stdin().read_line(&mut planet_input).unwrap();
println!("What is your weight in kilograms?");
let mut weight = String::new();
std::io::stdin().read_line(&mut weight).unwrap();

println!("Your weight is: {} and your selected planet is: {}", weight, planet_input);
}

We need to convert the weight from a string to a number. We will use the parse function to convert the string to a number. We will also lowercase the planet name to make it easier to compare.

use std::io;


fn main() {
 println!("Welcome to the weight on planets calculator!");
println!("---------------------------------------------");
println!("Enter a planet: ");
let mut planet_input = String::new();
io::stdin().read_line(&mut planet_input).unwrap();
let planet: String = planet_input.to_lowercase().trim().parse().unwrap();
println!("Enter your weight (kg): ");
let mut weight_input = String::new();
io::stdin().read_line(&mut weight_input).unwrap();
let weight: f32 = weight_input.trim().parse().unwrap();

println!("Your weight is: {} and your selected planet is: {}", weight, planet);
}

The next step is to calculate the weight of the object in the selected planet. To do this we will create a function that takes the weight and the planet as arguments and returns the weight of the object in the selected planet. We will use the match expression to compare the planet name and return the weight of the object in the selected planet.

fn weight_on_planet(weight: f32, planet: &str) -> f32 {
let mut weight_on_planet = weight;
match planet {
"earth" => weight_on_planet *= 1.0,
"jupiter" => weight_on_planet *= 2.34,
"mars" => weight_on_planet *= 0.38,
"mercury" => weight_on_planet *= 0.38,
"neptune" => weight_on_planet *= 1.12,
"saturn" => weight_on_planet *= 0.93,
"uranus" => weight_on_planet *= 0.92,
"venus" => weight_on_planet *= 0.91,
* => println!("Unknown planet"),
}
return weight_on_planet;
}

Now let's put everything together and print the weight of the object in the selected planet.

use std::io;


fn main() {
    println!("Welcome to the weight on planets calculator!");
    println!("---------------------------------------------");
    println!("Enter a planet: ");
    let mut planet_input = String::new();
    io::stdin().read_line(&mut planet_input).unwrap();
    let planet: String = planet_input.to_lowercase().trim().parse().unwrap();
    println!("Enter your weight (kg): ");
    let mut weight_input = String::new();
    io::stdin().read_line(&mut weight_input).unwrap();
    let weight: f32 = weight_input.trim().parse().unwrap();

    println!("Your weight on {} is {} kg", planet, weight_on_planet(weight, &planet));
}

fn weight_on_planet(weight: f32, planet: &str) -> f32 {
    let mut weight_on_planet = weight;
    match planet {
        "earth" => weight_on_planet *= 1.0,
        "jupiter" => weight_on_planet *= 2.34,
        "mars" => weight_on_planet *= 0.38,
        "mercury" => weight_on_planet *= 0.38,
        "neptune" => weight_on_planet *= 1.12,
        "saturn" => weight_on_planet *= 0.93,
        "uranus" => weight_on_planet *= 0.92,
        "venus" => weight_on_planet *= 0.91,
        _ => println!("Unknown planet"),
    }
   return weight_on_planet;
}

That's it! We just created a weight on planets calculator in Rust.

resources and references used in this post:

You can find the source code of the project here.

Thanks for reading!