Looping in Ruby

Looping support in Ruby is a bit different than in more traditional languages. In the Pickaxe it says “Ruby has pretty primitive built-in looping constructs” but you can do all the looping you really need to do, and Ruby does offer some nice touches.

The Goal

What I’m trying to mimmic here is the following C code

for (i=0; i<10; i++) {

    printf("%d n",i);

}

Foreach

The first question you should ask about this code is “what is it really trying to do?” It is designed to loop from 0 to 10, but why 10? Are their 10 somethings that you are trying to loop over? Could the number change? All of these questions are not clear from the code.

Most of the time I’m doing a loop like this, it is to loop over the elements of a collection (such as an array.) In Ruby, it would look like this…

my_array.each do |item|

  puts item

end

Yes, there are other ways to do this, but there are several advantages to using an iterator if you can.

  • You loose the ‘magic number’ aspect of the code (10 in this example.) If you go back later and make the array bigger, you don’t have to remember to change this code.
  • No ‘fencepost’ errors, or ‘off by one’ errors. You don’t have to worry about starting at 0 or 1, and wether you should test for i<10 or i<=10.
  • Most importantly, the intent of the code is now very clear. This has big implications for code testing and maintainability. Yes, you could comment the first loop to make it clearer, but comments can be forgotten, or get out of sync with the code itself. With an iterator, you really don’t need the comment. The intent is clear. Each item in the array is passed along and you do something to it or with it.

Foreach with an index

The one drawback of the basic iterator (.each) is if you also need the index of the item as it is called. The main place I use this is if I have a group of arrays that I need to work with. One program I wrote used an array for displacement, one for velocity, and one for acceleration. To calculate the displacement, I needed the corresponding values for velocity and acceleration.

In this case you can use .each_index instead of .each. The code would look like this

my_array.each_index do |i|

  puts my_array[i] + my_other_array[i]

end

The other situation where this can be useful is if you need to do something with the item before or after the current one. So if you need to do

puts my_array[i] + my_array[i-1]

kind of thing, you need to use .each_index instead of .each.

In my next post I will talk about the non-iterator loops in Ruby.

Advertisements

One Response to Looping in Ruby

  1. […] like loops In my earlier post, I talked about the use of iterators instead of pure loops in Ruby. When you can use them, they […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: