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:
Being mutable, with the
mut
keyword;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.