Rust Book: Chapter 3 - Control flow
Learned about variables, scalar and compound data types, functions, comments, if expressions, and loops.
Variables
Variables are immutable by default in rust. Once a variable is bound to a value, you can't change it, unless you explicitly declare your intent ahead of time using the mut
keyword at the time of the variable declaration.
fn main() {
let x = 5; //x is immutable
x = 6; // this line causes program to fail to compile
println!("value of x is: {x}")
}
Constants
Constants are always immutable, declared using the keyword const
, and the type of the value must be annotated.
const SECONDS_IN_DAY: u32 = 60 * 60 * 24;
Shadowing
Rust allows to declare a new variable with the same name as a previously declared variable. When we do this, we say that the second has shadowed the first.
fn main() {
let x = 5;
let x = x + 1; //x shadows the previous value of x
println!("The value of x is: {x}");
}
Data Types
There are 2 data types in rust: scalar and compound. A scalar type represents a single value. Rust has 4 primary scalar types: integers, floating-point numbers, Booleans, characters.
Integer types
Length | Signed | Unsigned |
---|---|---|
8-bit | i8 | u8 |
16-bit | i16 | u16 |
32-bit | i32 | u32 |
64-bit | i64 | u64 |
128-bit | i128 | u128 |
arch | isize | usize |
Each signed variant can store numbers from -(2n-1) to 2n-1 - 1 inclusive, with n being the number of bits that variant uses. Unsigned variants can store numbers from 0 to 2n-1. isize
and usize
types depend on the architecture of the computer the program runs on: 64 bits if running 64-bit architecture or 32 if 32-bit architecture.
Integer literals can be written in Decimal, Hex, Octal, Binary, Byte (u8 only)
Floating-Point Types
f32
and f64
are Rust's floating-point types. The default is f64
. All floating points are signed.
The Boolean Type
Boolean type in Rust is specified using `bool`.
fn main() {
let t = true;
let f: bool = false; //explicit type annotation
}
Compound Types
Tuples and Arrays are Rust's compound types.
A tuple is a general way of grouping together a number of values with a variety of types into one compound type. Tuples have fixed length: once created, cannot shrink or grow in size. We create a tuple by writing a comma-separated list of values inside parenthesis. Each position in a tuple has a type, and the types of the different values in the tuple don't have to be the same.
fn main() {
let tup: (i32,, f64, bool) = (500,, 6.4, true);
}
Array
Arrays have fixed length in Rust, and contain elements of the same type.
let a: [i32;5] = [1,2,3,4,5];
Arrays can also be initialised by specifying the initial value, followed by a semicolon
let a = [3;5]; // a will contain values like so: [3, 3, 3, 3, 3]
Practice
At the end of the Chapter, There are 3 practice programs to test knowledge:
- Convert temperatures between Fahrenheit and Celsius.
- Generate the nth Fibonacci number.
- Print the lyrics to the Christmas carol “The Twelve Days of Christmas,” taking advantage of the repetition in the song.
I plan to attach all 3 here this week. But since I have written the first, here you go 😊
Convert Temperatures between Fahrenheit and Celsius
/// Program to convert temperatures between Fahrenheit and Celsius
use std::io;
fn main() {
let target_scale: u8 = request_target_scale();
let reading = request_temperature_to_convert();
match target_scale {
1 => handle_celsius_to_fahrenheit_conversion(reading),
2 => handle_fahrenheit_to_celsius_conversion(reading),
_ => handle_unknown_temperature_scale(),
}
}
fn request_target_scale() -> u8 {
println!("Enter 1 for (celsius -> fahrenheit), or 2 for (fahrenheit to celsius):");
let mut target_scale = String::new();
io::stdin()
.read_line(&mut target_scale)
.expect("Invalid input");
let target_scale: u8 = target_scale.trim().parse().expect("Input not a Number");
target_scale
}
fn request_temperature_to_convert() -> f32 {
println!("Enter a temperature value to be converted:");
let mut reading = String::new();
io::stdin().read_line(&mut reading).expect("Invalid Input");
let reading: f32 = reading.trim().parse::<f32>().expect("Input not a Number");
reading
}
fn celsius_to_fahrenheit(reading: f32) -> f32 {
((9.0 / 5.0) * reading) + 32.0
}
fn handle_celsius_to_fahrenheit_conversion(reading: f32) {
println!(
"{reading}°C is {converted:.2} °F",
converted = celsius_to_fahrenheit(reading)
)
}
fn handle_fahrenheit_to_celsius_conversion(reading: f32) {
println!(
"{reading}°F is {converted:.2}°C",
converted = fahrenheit_to_celsius(reading)
)
}
fn handle_unknown_temperature_scale() {
println!("Unsupported unit. Cannot make conversion")
}
fn fahrenheit_to_celsius(reading: f32) -> f32 {
(reading - 32.0) * (5.0 / 9.0)
}
Member discussion