Ruby Loops Demystified

posted in: ones and zeros | 0

Note: This explanation of looping is geared towards absolutely-100%-new programmers. Consider yourself warned. Also, I highly recommend typing the examples into a new Ruby file and then running it to see the output and get a better feel for what is going on. Really – it helps!

Looping is a fundamental concept in computer programming. It is often necessary to repeat the same set of instructions multiple times, and rather than write those instructions over and over and over, you can use a loop to automate that repeating.

Often, you don’t even know exactly how many times you will need to repeat something, so inside the loop you can include a way for the computer to figure it out for you. So instead of saying “Do this 5 times,” you’ll say “Do this x times.” An added benefit here is that if you need to change the number of times those instructions are repeated, you’ve built some flexibility into the code.

But I digress.

There are multiple ways to loop over code in Ruby, including both “language constructs” (built in syntax for expressing logic) like the reserved keywordswhileuntil, and for; as well as “methods” (ways to do something to something) like .each() and .times().

Perhaps the best way to explain these different kinds of loops is to first differentiate them by how they work.

Conditional Loops

Conditional loops execute the specified code until a certain condition is met. For example, you want to add candles to a birthday cake until you’ve reached the age of the birthday child. (You can also execute the specified code while a certain condition is still the case - we’ll see that in a second.)

Here you find yourself with a true or false situation: is the number of candles equal to the age yet? No? (False?) Okay, let’s add another candle. Now is the number of candles equal to the age? (True or false?) And so on.

Until Loops

Ruby has a keyword that is perfect for this candle-adding situation, and not surprisingly, it is until. Ruby likes its mnemonic word choices, so that it almost seems like you’re speaking English to the computer. (Other languages don’t necessarily work this way.)

There are two ways to write this loop: as a conditional “statement” or as a conditional “modifier.”

Statement syntax for our birthday example would be:

candles = 0  #because you haven't put any candles on the cake yet
age = 5  #have to specify the age or the computer won't know when to stop adding candles!

until candles == age  #here we specify the condition we want to meet: candles equals age
   candles = candles + 1  #here we add 1 to the number of candles, and this is the part 
   that gets repeated until the above condition (does the # of candles equal the age?) is met
end  #"end" tells the computer that the until loop stops here

Modifier syntax would look like:

 

candles = 0
age = 5

candles += 1 until candles == age  #add to candles until candles equals age

(Fyi: “+=” is a shorthand for “candles = candles + 1″. Blew my mind first time I saw that.)

As you can see, assuming the code you’re repeating isn’t super complicated, the modifier version is much simpler and easier to read than the statement version.

And because Ruby seems to always have at least three different ways to do the exact same thing, you can use another version of modifier syntax as well:

candles = 0
age = 5

begin
  candles += 1
end until candles == age  #this seems a bit more confusing, in my opinion

While Loops

Related to the until loop is the while loop. It also uses a condition to decide how many times to do something. until does something until the condition is true (so it starts out “false”), but while is the opposite:

While any of the candles are still lit, keep blowing.

In code, this looks like either (statement syntax):

lit_candles = 5

while lit_candles > 0
  lit_candles -= 1  #keep blowing!
end

or (modifier syntax):

lit_candles = 5
lit_candles -= 1 while lit_candles > 0

Until vs While

So what’s the difference between these? Aren’t they pretty much two different ways to accomplish the same thing? Couldn’t I just say “until lit_candles is 0, keep blowing”?

Yes. Yes you could. In fact, a lot of other languages don’t even have an until option, they only have while. The reason we have two options here is because Ruby was designed to read more like English than some of the older programming languages.

When you’re choosing whether to use while or until, just ask yourself how you would state the situation in plain ol’ English. “I want to nap until 2:00.”" “While I’m at work I want to check my email hourly.”" Whichever option makes it easier to read and understand, that’s the option you should choose.

So that’s conditional loops, but what about iterative loops?

Iterative Loops

Here, instead of having a true/false condition that we’re working with, we simply want to do something a certain number of times. We want to iterateover a collection of data, repeating an action as many times as there are bits of info in our collection.

For Loops

To keep things simple, I’ll use an array in the examples, which is pretty much just a list of things. For every “thing” in the list, we do something once. In fact, the syntax here uses for:

presents = ['coloring book', 'stuffed animal', 'bouncy ball', 'puzzle']  #here we're 
telling the computer what our array has listed inside: 'coloring book', 'stuffed animal', etc.

for present in presents  #see note below 
  puts present  #put each item on the screen where we can see it
end  #again, saying "end" lets the computer know that's all of the code it needs to repeat

Note: Ruby doesn’t know what a “present” is – this is just the name I chose to represent each and every item in the list as we go through that list. I could have chosen “a” or “x” or “hurricane” and it would still work – the names I chose just make more sense in this (birthday party) context than “hurricane” does. It’s like in algebra, where “x” and “y” don’t actually have any inherent value, they’re more like placeholder names.

Ruby also doesn’t know what a “candle” is, or “age,” or “lit_candles” – these are all just names that I’ve used to help someone reading the code understand what I’m talking about. Unfortunately, very new beginning coders can be confused by this because they haven’t memorized all the words that Ruby doesknow. For this reason, it can be a good idea to have a list of keywords handy so you can double check when you’re not sure! (If you didn’t understand this until now, go re-read the code above and see if it makes more sense.)

Looping Methods

The for loop example given above is all well and good, works totally fine, but Ruby has some additional, special ways to loop over your data. The two most basic ones are each and times.

Each Loops

each does very nearly the exact same thing as for, so unless you know you need to use for, you should try to use each instead (more about that in a bit):

presents = ['coloring book', 'stuffed animal', 'bouncy ball', 'puzzle']

presents.each do |present|  #for each item in presents do:
  puts present  #put the item on the screen
end

We have to give some name to specify “individual thing in the list,” and with the each method, our iterator variable “present” goes between two pipes: | | (as opposed to the for syntax which puts it between for and in).

Each vs For

So which version should you use? It is considered more idiomatic - “more Ruby” – to use each than to use for.

The reason why, though, might be a little too much for an absolute beginner to wrap their head around: each creates an iterator variable (ie “present” in our presents example) that lives only within the “scope” (context) of the each ”block” (the code between do and end).

But, for now, you don’t actually have to understand the why of it. Just remember if you use each you’re less likely to accidentally get yourself in trouble: when using each, the iterator variable goes away once you’re done with that bit of code, but for‘s iterator variable persists and so it could accidentally alter something you don’t want to alter. Plus… it’s what people expect you to do. Keep the peoples happy.

Times Loops

The times method is a similar approach to each, in that it’s also more idiomatic:

3.times do  #for a certain number of times, do the following:
  puts "Happy birthday!"" 
end

Again, one of the important ideas behind Ruby is that the code should be easy to understand. The above is certainly easier to read than, for example, our candle-inserting until loop (in this particular example’s times loop, anyway – you could definitely make it more complicated if you need to do something more complicated!)

Loop de Loop

And there we have our primary ways of repeating chunks of code in Ruby:

 

  • until
  • while
  • for
  • each
  • times

 

You will get lots of practice with these, because they really are used ALL THE TIME. Some additional resources in case you still have questions: