- Write an
if...end
statement - Write an
if...else...end
Statement - Write an
if...elsif...else...end
Statement - Use statement modifiers to change default sequence
We've covered the default sequence Ruby follows when reading and executing
a Ruby file. Let's teach the sequence to change by using the selection
statement: if...end
.
In this lab, we will cover the basics of if...end
statements. At the end, you
will need to write your own code and pass the included test.
To write a basic if...end
statement in Ruby, the first line should start with
if
, followed by a condition. If this thing is true...
if <something that is either true or false>
Following this line, we can add some code that we want to run when the if
statement is true. This code is conditional - it may or may not run! To let Ruby
know we're done writing conditional code, we add end
.
if true
puts "This code runs!"
end
Run in IRB, the above code will output
This code runs
=> nil
The code inside the if...end
statement below will never run:
if false
puts "This code does not run. You will not see this in IRB"
end
Instead of writing true
or false
, we typically use a variable or expression.
run_code_inside = true
puts "Code before if...end"
if run_code_inside
puts "code inside"
end
puts "Code after if...end"
Try entering this code in your file and try running it. The output should be the following:
Code before if...end
code inside
Code after if...end
Following the default sequence we:
- Assign
run_code_inside
- Print out with
puts "Code before if...end"
- Reach the
if
statement - Evaluate the expression to the right of the
if
statement - Since the expression
run_code_inside
evaluatestrue
, we perform the code between theif
andend
reserved words - Print out with
puts "Code after if...end"
Try changing run_code_inside
from true
to false
and see how the
default sequence operates:
- Assign
run_code_inside
- Print out with
puts "Code before if...end"
- Reach the
if
statement - Evaluate the expression to the right of the
if
statement - Since the expression
run_code_inside
evaluatesfalse
, we skip to theend
reserved word - Print out with
puts "Code after if...end"
We are essentially saying we want to execute our code, but we want to "mute" this one part of if.
A slightly more advanced version of if...end
is if...else...end
. In this
code, we are guaranteed that the code in ONE of the two blocs will run (as the
Boolean expression can only ever be one of two choices).
chance_of_rain = 0.2
puts "Let's go outside!"
if chance_of_rain > 0.5
puts "Pack an umbrella!"
else
puts "Enjoy the fine day!"
end
puts "Oh, and always wear sunscreen!"
The output is the following when the chance of rain is <= 0.5
:
Let's go outside!
Enjoy the fine day!
Oh, and always wear sunscreen!
If we change chance_of_rain
to 1
, we get:
Let's go outside!
Pack an umbrella!
Oh, and always wear sunscreen!
In an if...else...end
statement, if the expression to the right of if
evaluates true
, the work between if
and else
is run. If the expression to
the right of if
evaluates false
, the code between else
and end
runs.
Sometimes choices are strictly limited to a path A or path B option, sometimes
there's a third, fourth, option. In that case we need the
if...elsif...else...end
statement.
chance_of_rain = 0.2
if chance_of_rain <= 0.25
puts "Pack a sun shelter!"
elsif (chance_of_rain > 0.25 && chance_of_rain < 0.75)
puts "Pack an umbrella!"
else
puts "Stay home and read Hegel."
end
Try filling in a table by changing the value of chance_of_rain
. You'll see
that you get different output!
chance_of_rain value |
Output |
---|---|
0.0000001 |
|
0.2 |
|
0.2000001 |
|
0.3 |
|
0.9 |
|
1000 |
|
-23 |
Ruby has a useful feature called a statement modifier that allows you to put a conditional at the end of a statement. For example, let's consider this statement:
puts "Hey, it's 2019!"
However, we don't want to say "Hey, it's 2019!" every time this code is run. We
only want to say it's 2019 if it's actually 2019. This is a good case for
an if
statement modifier.
puts "You know what year it is??"
this_year = 2019
puts "Hey, it's 2019!" if this_year == 2019
With output:
You know what year it is??
Hey, it's 2019!
Now, with the statement modifier if this_year == 2019
we are only putting it
if the year is, in fact, 2019.
We can also use unless
in a statement modifier as well.
LOGICAL FACT: The English Logician Augustus DeMorgan proved that "if-not" is equal to "unless." This had huge implications for the construction of CPUs, but he discovered it in the era of inkwells and steamer ships. See DeMorgan's Laws
this_year = 2019
puts "Hey, it's not 2019!" unless this_year == 2019
STRETCH: Here we've hard-coded the year in
this_year
. If you want to ask Ruby to tell you the year, ask IRB whatTime.now.year
gives you. That expression could be assigned tothis_year
if you want more robust — and thus better — code! It's a common practice for developers to try out an expression in IRB, verify it, make sure they understand it, and then integrate it into their code.
Now that we've seen a few examples of selection statements, it is time to test
our knowledge. Your task is to write an if...else...end
statement. For this
statement, the condition will be based on the current time:
- If the current second is an even number, output
Even!
- If the current second is an odd number, output
Odd!
To determine the exact time, we can rely on Ruby's built-in Time
class. In
IRB, running Time.now
will give you the current time:
2.6.1 :001 > Time.now
=> 2020-02-25 09:00:33 -0500
In the example above, the time is 09:00:33 AM. Similar to a String
,
Time
is a class in Ruby and Time.now
returns a Time
object. It
isn't a String
and it isn't an Integer
, but like them, it can be stored in
a variable.
2.6.1 :002 > current_time = Time.now
=> 2020-02-25 09:07:47 -0500
And it can be converted to either:
2.6.1 :003 > current_time.to_s
=> "2020-02-25 09:07:47 -0500"
2.6.1 :004 > current_time.to_i
=> 1582639667
Note: Converting a
Time
object to an integer returns Epoch time, the number of seconds since January 1st, 1970.
So we can get the current time, and we can convert this time into an integer.
But how can we incorporate this into an expression that evaluates to true
or
false
?
Try to work out a solution using what you've learned about if...else...end
statements and Boolean expressions. Write your answer in lib/if_else_end.rb
and run learn
to see your test progress.
There are multiple ways to solve this lab and we will look at two possible
solutions. Remember, the task is to output either Even!
or Odd!
depending on
the current second.
We can write out a lot of the code without knowing all of it
exactly. First, we can write the if...else...end
statements, but we'll leave
out the condition for the moment:
if true
puts "Even!"
else
puts "Odd!"
end
With the setup above, the output will always be Even!
. To change that, we will
need to replace true
with an expression based on Time.now
that deterrmines
if the current second is even or odd.
We might start by capturing the Time.now
value:
current_time = Time.now
Convert it to an integer
current_time = current_time.to_i
If we recall the lesson on arithmetic, the modulo operator, %
, can be used to
tell if an integer is even or odd:
current_time = Time.now
current_time = current_time.to_i
if current_time % 2 == 0
puts "Even!"
else
puts "Odd!"
end
The expression current_time % 2
will either return a zero or one. If we add
== 0
to it, the complete expression will compare the results of
current_time % 2
to zero. Therefor, if the current_time is an even second, the
expression will evaluate to true
.
We could actually clean up our code a bit if we choose, and skip using the
current_time
variable entirely:
if Time.now.to_i % 2 == 0
puts "Even!"
else
puts "Odd!"
end
Taking a quick look at the [Integer
class][integer] in Ruby, it turns out
there is a built-in tool for checking if any integer is even - the .even?
method:
current_time = Time.now
current_time = current_time.to_i
if current_time.even?
puts "Even!"
else
puts "Odd!"
end
This should now satisfy the test requirements. Run learn
to confirm you've
passed the two tests in this lab.
Selection statements are a core part of programming. They allow us to make our
code more dynamic. Our example based on seconds may not be the most applicable,
but there are definitely times when we might want some piece of code to only run
on specific hours or days. More often, especially as we are learning,
conditional statements are a great way to output our own messages. We could,
for instance, confirm our own beliefs about a piece of code we've written by
adding an if...end
statement after it and comparing the result of our code
against what we expect.
result = 2 + 2
if result == 4
puts "We've done it!"
end