Unlock Your Python Backend Career: Build 30 Projects in 30 Days. Join now for just $54

Chapter 3: Building with Rust

Chapter 3: Building with Rust

Building A simple love calculator in Rust

Building A simple love calculator in Rust

We all had our own shares of love plays while young. Perhaps you remember the popular “flames” method.

Here we’ll be using a basic formula to derive compatibility percentages:

(length_of_shorter_name/length_of_longer_name) × 100

Pseudocode:

Rust way of doing things diverges from the other languages, hence the need for pseudocode to outline steps in our code.

This program calculates the love compatibility of a male and a female with their names as input:

function handle_input(arg: memory_address_to_store_input) {
	* accepts `memory address` *
	* returns nothing *

	request input from user
	trim whitespace from user input
	store cleaned input into `arg`

	returns the length of the input
}

function calculate_compatibility(name1: String, name2: String) {
	* accepts Strings for both input *
	* returns number as percentage *
	if length of name1 > length of name2:
		percentage = (length of name2 ⁄ length of name1) x 100
	else if length of name2 > length of name1:
		percentage = (length of name1 ⁄ length of name2) x 100
	else: * lengths are equal *
		percentage = 50
}

function main() {
	initialize `name1` as string
	initialize `name2` as string

	name1_count = handle_input(memory address of name1)
	name2_count = handle_input(memory address of name2)

	compatibility =  calculate_compatibility(name1_count, name2_count)

	print compatibility
}

Code

First, we’ll use cargo to initialize our project. Cargo will help manage compilation and other nitty-gritty things involved in running out of code.

To initialize, head to the terminal and type:

cargo new love_calculator

The main function

use std::io;

fn main() {
	let mut name1 = String::new();
	let mut name2 = String::new();
}

The first line of our program would involve bringing functionality from the standard library into scope.

The io module as explained in its documentation “… contains a number of common things you’ll need when doing input and output”.

As with many C-like languages, the entry point of any Rust program is the main function. Declaring a function uses the keyword fn and the name of the function.

It has a syntax like so:

fn function_name(arg1: type, arg2: type, ...argn: type) → return_type {
	function body; //statements end in a semicolon
	return value	//return values do not require a semicolon or the ‘return’ keyword. If you need a semicolon, perhaps as part of a logic, you can then use the return keyword
}

In the absence of a return type, Rust implicitly returns what is called the Unit Type, written as Ok().

The concept of Null does not exist in Rust, instead, Rust represents it with a type called None as showing the absence of a value. Its counterpart is Some which could be used to wrap any data type.

In the main function, we declare two variables, name1 and name2 using the let keyword as:

  1. Being mutable, with the mut keyword;

  2. As a String: There are two types of strings you’ll encounter in Rust, the other is a string literal.

As with many other languages, the new method is used to initialize an instance of an object or Struct in this case.

Rust makes use of Structs and Enums as opposed to objects and classes for abstracting data.

We’ll be taking a closer look at these two concepts later on.

Right now, let’s get the our actual Love Calculator Code out of the way.

Below is the code that will produce our love calculator in Rust based on the name input of the user.

use std::cmp::Ordering;
use std::convert::TryInto;
use std::io;


fn get_input(var: &mut String) -> i32 {
    io::stdin()
        .read_line(var)
        .expect("Failed to read line");

    var.chars()
        .count()
        .try_into()
        .expect("Length of name is too large!")
}

fn calculate_compatibility(name1_count: i32, name2_count: i32) -> f32 {
    match name1_count.cmp(&name2_count) {
        Ordering::Less => {
            ((name1_count as f32 / name2_count as f32) as f32 * 100.0) as f32
        },
        Ordering::Greater => {
            ((name2_count as f32 / name1_count as f32) as f32 * 100.0) as f32
        },
        Ordering::Equal => {
            50.0
        }
    }
}


fn main() {
    let mut name1 = String::new();
    let mut name2 = String::new();

    println!("Enter first person name: ");
    let name1_count = get_input(&mut name1);

    println!("Enter second person name: ");
    let name2_count = get_input(&mut name2);

    let compat_value = calculate_compatibility(name1_count, name2_count).floor();
    
    println!("Love compatibility between {} and {} is {}%", name1.trim(), name2.trim(), compat_value);
}

Now, let’s move down to explaining each of the concepts used in the code below to get a clearer understanding of how Rust handles certain programming concepts.

Whenever you're ready

There are 4 ways we can help you become a great backend engineer:

The MB Platform

Join 1000+ backend engineers learning backend engineering. Build real-world backend projects, learn from expert-vetted courses and roadmaps, track your learnings and set schedules, and solve backend engineering tasks, exercises, and challenges.

The MB Academy

The “MB Academy” is a 6-month intensive Advanced Backend Engineering BootCamp to produce great backend engineers.

Join Backend Weekly

If you like post like this, you will absolutely enjoy our exclusive weekly newsletter, Sharing exclusive backend engineering resources to help you become a great Backend Engineer.

Get Backend Jobs

Find over 2,000+ Tailored International Remote Backend Jobs or Reach 50,000+ backend engineers on the #1 Backend Engineering Job Board