Flow Control
When programming you will find that you can achieve the same results by taking different paths, whether for performance purposes or readability.
In this lesson we will try to make a piece of code to behave on different ways, depending on a or multiple conditions
What are you going to learn?
- Understand how to define multiple flows within a piece of code
- Usage of
if
andunless
to control flow - Handle multiple decision branches with
else
andelsif
- Use
while
,times
anduntil
to repeat steps - Understand what an infinite loop
- Correctly utilize the basic syntax for flow controle mechanisms in Ruby
Remember that the alternatives we publish here, are just that, you may find better or worse paths to get the same result. We will try to show you which tools are commonly better for the job, or at least are more commonly used.
What is a condition?
A condition is a statement that may be true
or false
, and in programming this is called a Boolean.
A boolean is another data type inside Ruby, therefore you can assign variables to true
of false
.
play_music = false # => false grill_chicken = true
By their own, there is nothing much you can do, but we will use the condition evaluation by comparing booleans.
There are a bunch of comparison operators you can work with:
==
is used to check if two statements are the same>
as in math, is used to check if the left value is greater than the one on the right<
is used to check if the left value is less than the one on the right>=
and<=
if to check for values to be greater/less or equal to the second one!=
is used to check if two statements are different
Here are a bunch examples:
sun == hot #=> true 3 > 5 #=> false 3.14 <= 144 #=> true hot != cold #=> true
There is also a way to inverse a boolean, just preppend the !
operator to the statement. By doing this you will always get the opposite boolean
value. There is an alias
for this by using the word not
instead of the !
, but this is only for Ruby. We prefer the !
operator, as it is more
widely use across other languages.
!true #=> false hot_outside = true !hot_outside #=> false not hot_outside #=> false
There is also a bunch of built-in methods in Ruby that evaluate into booleans:
["Tarzan", "Hercules", "Frozen"].empty? #=> false 1.odd? #=> true ["Tarzan", "Hercules", "Frozen"].include? "Moana" #=> false { name: "Tarzan", release_date: Date.new(1999, 7, 16) }.has_key? :name #=> true
As you may already notice, all of this methods end with a ?
sign, which it is just a standard un Ruby to visually define the methods return a boolean, and even though
we highly recommend this, you are not obligated to do it.
If statement
Let's start playing with some decisions in our code. A simple if
statement will create two possible ways the code can follow.
A example in plain english:
If I'm hungry, then I can order some food from my local restaurant
if hungry == true order_food_from_local_restaurant end order_food_from_local_restaurant if hungry == true
Both examples shown above work the same, just mind that the second one only work if you don't have an else
statement.
An if/else
statement would look like:
if hot == true jump_into_the_pool else turn_on_heater end
In the example above, the code will take a decision based of the two scenarios presented, whether is hot or not. There could be a third scenario. Actually, there is no limit when it comes to scenarios:
if hot == true jump_into_the_pool elsif raining == true take_out_umbrella elsif windy == true get_windy_jacket else turn_on_heater end
Given the example above, take this into consideration:
- Each condition is evaluated in order
- The
else
comes after all of theelsif
- The
else
is optional, you could also write it with aelsif
|| and &&
So far, all of the examples we have provided are based on single comparisons, whether is hot
or rainy
or something else, but in many cases you may want to compare for
multiple conditions. You achieve this through the ||
and &&
operators. ||
will always evaluate to true
if one of the conditions is true. &&
will always evaluate to true
if
all conditions are true
.
We provide a table of truth so it may be easy to visualize:
||
Condition 1 | Condition 2 | Evaluates into... |
---|---|---|
True | True | True |
True | False | True |
False | False | False |
False | True | True |
&&
Condition 1 | Condition 2 | Evaluates into... |
---|---|---|
True | True | True |
True | False | False |
False | False | False |
False | True | False |
Another way to remember this, is to use basic math operations, so that every true
is equals to 1 and every false
to zero. For the ||
use sums and for the
&&
use multiplication:
||
Condition 1 | Condition 2 | Evaluates into... |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 0 | 0 |
0 | 1 | 1 |
&&
Condition 1 | Condition 2 | Evaluates into... |
---|---|---|
1 | 1 | 1 |
1 | 0 | 0 |
0 | 0 | 0 |
0 | 1 | 0 |
Now some practical examples with Ruby:
heroe = "Black Widow" power = "Fighting Skills" heroe == "Black Widow" && power == "Fighting Skills" #=> true heroe == "Black Widow" || power == "Can fly" #=> true heroe == "Black Widow" && power == "Can fly" #=> false
Quick try: What would the following code return?. Try to explain why that happens, and how would you rewrite it
heroe = "Hulk" heroe == "Hulk" || "Black Widow"
Looping in Ruby
Loops are a very powerful tool we as developers have to our disposal, in order:
- to repeat a task as many times as we want
- or as long a as condition is met.
In this part of the lesson, we will learn to use times
, while
, until
.
times
This type of loop executes the exact number of times:
3.times do # Include here the code to execute 3 times end
You can also add what is called block variable to access the current iteration:
3.times do |number| puts number end
This will output:
0 1 2
while
The while
loop will execute code as long as the condition is met:
while hungry? eat end
Another use for this, is having an actual counter and reduce it with each iteration:
number_of_persons = 4 while number_of_persons > 0 feed_person number_of_persons = number_of_persons - 1 end
until
The until
loop will execute code as long as the condition is met:
until full? eat end
Another use for this, is having an actual counter and reduce it with each iteration:
number_of_persons = 0 until number_of_persons > 4 feed_person number_of_persons = number_of_persons + 1 end
Infinite loop
When working with loops
you may encounter that sometimes the iterations would never stop, because of the
condition will always meet. For example:
number_of_persons = 4 while number_of_persons > 0 feed_person end
As you can see we are not reducing the number_of_persons
variable, therefore the while
loop will never be able to finish. This is what is called an
infinite loop, and it commonly ends up consuming all the memory assigned.
Exercises
Remember we have provided a repository with a bunch of exercises for you to complete. You can find it here
You can finde them under /ruby-exercises/Module1/flow-control
.