Loops & Basic Logic Flows
This section will cover two foundational parts of Rust and programming in general: loops and logic flow.
Basic Logic Flows
Logic flows, sometimes called control flows, allow for conditional statements, such as if
, to be
possible. It allows for branching logic to be implemented for a program based on boolean
values.
Using if
As said before, implementing logic based on whether something is true or not would be very useful
if
statements are the cornerstone of conditional logic.
let this_is_true: bool = true;
if this_is_true {
println!("Less trust, more truth!");
}
The above code showcases a very simple example. The statement this_is_true
is set to a boolean
value, true
, which will execute the code within the brackets when evaluated by the if
statement.
It's also possible to use an exclamation mark (!
) to further diverge logic:
let this_is_true: bool = true;
if !this_is_true {
println!("Less trust, more truth!");
}
This no longer prints, as it looks for the opposite of true
- false
.
A more realistic example is checking if a number is higher or lower than expected, like seeing if a bank balance is over $100.
let bank_balance = 101;
if bank_balance >= 100 {
println!("More than 100 dollars");
}
Using else if
and else
A single if
statement can only be used so much. Using else if
, we can create branches of logic
within a program:
let bank_balance = 56;
if bank_balance >= 100 {
println!("More than, equal to, 100 dollars");
} else if bank_balance % 2 == 0 {
println!("You have an even balance!");
} else if bank_balance <= 0 {
println!("Uh oh, it appears you're in debt!");
} else {
println!("More than 0, but less than 100!");
}
Using match
You can also use a match statement to perform similar logic, which we will investigate later. A
match
statement is the most basic form of pattern matching:
let age = 18;
match age {
16 => println!("Old enough to drive"),
18 => println!("An adult"),
_ => println!("Irrelevant age")
}
Iterating with loops
Loops in Rust are very useful expressions, which, if you recall, produce a value as a result of some operation.
Although Rust supports five types of loops, we will go over the most common types:
- The
loop
expression - an infinite loop which goes tillbreak
is called. - The
while
expression - a loop that continues until a condition is true or false. - The
for
expression - a loop that is useful for iterating over a collection of items.
Infinite loops: loop
Using the loop
keyword, we can define an expression that iterates, or loops, infinitely:
fn main() {
loop {
println!("Print forever!");
}
}
This type of loop is typically used to keep trying some operation until a condition has been fulfilled.
Conditional loops: while
A while
loop will automatically stop once a condition has been fulfilled. An example would be
looping until a number has reached a certain limit:
fn main() {
let mut x = 0;
while (x <= 10) {
println!("x is now: {x}");
x += 1;
}
}
In this case, we define a mutable variable x
. The while loop, which defines a condition while x is
less than or equal to 10
(x <= 10
), executes the logic until the condition for x
is met.
A while loop could also iterate over a collection if needed:
fn main() {
let months = ["Jan", "Feb", "Mar", "Apr"];
let mut index = 0;
while (index <= months.len() - 1) {
println!("The month is now: {}", months[index]);
index += 1;
}
}
This is a bit clumsy, not to mention not friendly to any updates to the months
array - an index
could be out of bounds if we add or take away any elements from the array. Luckily, there is a
better way to accomplish this.
Looping over collections: for
The for
loop is primarily used for looping over a collection of items, such as an array. You may
recall that we used a for
loop to loop over several course modules.
Let's refactor the code from while
to for
:
fn main() {
let months = ["Jan", "Feb", "Mar", "Apr"];
for month in months{
println!("The month is now: {}", month);
}
}
Besides being much more concise, there is no worry about having an index out of bounds
error.
Try it out!
What is happening here?
All the core loops are illustrated above. Notice the break
keyword being used within loop
, so
the playground does not run infinitely (and so other loops can run!).