Today we're going to go over the concept of looping in Ruby. Looping is an action that tells our program to do the same thing over and over again with a few lines, rather than manually typing out our desired loop length.
Why Loop?
Simple answer: because as programmers we aspire to be as lazy as possible.
Think a minute about writing a program that requires you to perform an action 5 times, then imagine having to do it 100 times. What problems could you potentially run into typing all occurrences manually? First is a matter of convenience, even if you copy/paste to ensure all the lines are exactly the same, that's still a tedious manual task that takes away time from improving your program elsewhere. Next, what if you lose count after say 47? What if you accidentally type it in only 97 times? 103 times? This could potentially cause your program to not work as intended in other parts of your code as well.
Loops automate this process for us with only a couple lines of code in Ruby. A program that would require a String
to be repeated 100x would use 100+ lines of code if manually looped. You can perform the same functionality in Ruby with about 3 lines of code:
100.times do
puts "Here we go 'round!"
end
And just like that, a seemingly daunting task is complete in a matter of seconds!
Ruby has several different types of loops, some with overlapping functionality and some meant to be more niche in use. We'll go over some of the more common types of loops and explain them in greater detail below.
Times Loops
Let's start by breaking down the above loop, and highlight the keys that make this function:
100.times do
puts "Here we go 'round!"
end
-
100.times
is the number of times we want our program to perform the following action. The number in front oftimes
also serves as a built-inbreak
of the loop, where some other loop types require you to add it in elsewhere. - the
do
/end
creates a block that tells our program what action we want to perform. In this caseputs
"Here we go 'round!" Thedo
/end
block will be a common participant in a number of Ruby lessons.
The beauty of Ruby is it's designed with being programmer-friendly as it's #1 priority. times
is one of the best examples of that in the entire language.
The "Loop" Keyword
Next up is the loop
keyword. loop
is the simplest construct we have for looping in Ruby. It will just execute a block (the action(s) between do
/end
) over and over until it is told to stop.
Let's built a similar method as above from scratch:
loop do
puts "Here we go 'round!"
end
This will put the string "Here we go 'round!" into our console in an eternal loop until we stop it with ctrl
+c
. Not terribly useful overall in its current form if you ask me. Let's add a break
command to stop the loop on its own:
loop do
puts "Here we go 'round!"
break
end
# returns =>
#Here we go 'round!
So now we have a "loop" that only executes our desired command once. The thing is loop
is so simple, that it requires a bit more effort to work at the same level as times
, which kind of defeats the point as Rubyists.
If we wanted to write a loop
command equivalent to our times
command above, we would have to add a counter to keep track of when to break the loop like such:
counter = 0
loop do
counter += 1
puts "Here we go 'round!"
if counter >= 100
break
end
end
That is almost triple the number of lines it took our times
loop to accomplish the same task.
Note You may be wondering what the +=
is doing. It basically performs the same function as the line counter = counter + 1
which increments and keeps track of the updated value of the counter
variable. It simply condenses the code.
Since we have a counter
variable, I'll take this opportunity to demonstrate how to keep track of variables inside loops. Stop me if this looks familiar to you:
counter = 0
loop do
counter += 1
puts "Here we go 'round #{counter} times!"
if counter >= 100
break
end
end
#returns =>
#Here we go 'round 1 times!
#Here we go 'round 2 times!
#...
#Here we go 'round 99 times!
#Here we go 'round 100 times!
Yup, we can interpolate with #{variable}
inside loops to display and even manipulate the current values of variables.
While Loops
while
loops provide a unique approach to a similar end. Basically while
translates the given condition to a boolean
, and if that condition is true
the while
loop will then execute until the condition is false
. Like times
while
is it's own built-in break
, so there is no need to declare a direct break
inside the action like with loop
. Writing a loop like above in this style would look like this:
counter = 0
while counter < 100
puts "Here we go 'round!"
counter += 1
end
Removing the break
command saves us some space, but in a strict counting situation while
still isn't as advantageous as the times
loop. However, in slightly more complex programs, while
has some strong advantages over times
. For example, if we had an adventurer who was poisoned and losing health, we would want to keep track of our HP so we know when to use our auto-revive potions, right? And we would definitely need a reminder to pop up when we died from the poison too, right?
hp = 100
status = "poisoned"
potions = 2
while status == "poisoned" && hp >= 1
hp -= 1
puts "HP: #{hp}"
if hp == 0 && potions >= 1
puts "You've used an auto-revive potion!"
potions -= 1
hp += 100
status = "normal"
puts "HP: #{hp}"
elsif hp == 0 && potions == 0
puts "The poison was too much to bear!"
end
end
This code is a bit busy, but doesn't contain anything we haven't covered already! The gist is we set initial values for hp
, status
. & potions
and manipulated them throughout the while
loop. Using times
in this situation would require multiple loops and more lines for what would likely be a less desirable result. Also note the do
in while
is not necessary
On a more personal note, I'm glad we had enough potions to survive being poisoned!
Until Loops
unitl
is basically the inverse of while
. Where a while
loop executes when something is true
, an unitl
loop will execute until something becomes true. For example:
counter = 0
until counter == 20
puts "Almost 20!"
counter += 1
end
Just like while
the do
is optional.
While you can do complex code with until
, in my opinion, the best time to use until
is as a statement modifier. Example:
i = 0
puts i += 1 until i == 5
#returns =>
#1
#2
#3
#4
#5
This is a very simple example, but it does an effective job of manipulating the value of a variable to the desired number in only 1 line of easy to read code.
Concluison
The key to loops in Ruby, and any programming language really, is knowing what loop is best used in a given situation. Do you want to repeat an action a specific amount of times with little additional context? Use times
!. Want to drown someone special in your eternal love? Use loop
(with no break
!)! Wanna get a little more complex with your code? Use while
! Need a simple and precise statement modifier? Use until
!
Loops Lab
Now that you've learned about Loops
, let's head on over to the Ruby Loops Lab and apply those lessons by completing the assigned tasks.
Top comments (0)