Main Content

For loop - checked once, or evety time? Ruby v Perl comparison and contrast

Archive - Originally posted on "The Horse's Mouth" - 2010-04-07 19:18:58 - Graham Ellis

Although may aspects of Ruby are inherited (in a non-OO way!) from Perl, there are some distinct differences too; a classic for loop in Perl has its end condition checked every time around the loop, but a Ruby for loop sets up an iterator at the start, so that if something changes within the loop evaluation context, the loop does not dynamically adjust. Let me show you an example.

Here's a for loop in Ruby:

stuff = ["Tom","Dick","Harriet"]
 
for v in 0...stuff.length do
  print "#{v+1} ... #{stuff[v]}\n"
  stuff[stuff.length] = "Bob"
  end
  
p stuff


In which the loop runs 3 times because that's the number of times that's calculated before the loop starts.

Dorothy-2:ra10 grahamellis$ ruby evalo.rb
1 ... Tom
2 ... Dick
3 ... Harriet
["Tom", "Dick", "Harriet", "Bob", "Bob", "Bob"]
Dorothy-2:ra10 grahamellis$ ]


But in Perl, using the classic from, to, step, the end condition is checked every time. So if we write the equivalent code in Perl:

@stuff = ("Tom","Dick","Harriet");
  
for ($v=0; $v<@stuff; $v++) {
  print "$v >>> $stuff[$v]\n";
  $stuff[@stuff] = "Bob";
  }
  
print ("@stuff\n");


we get an infinite loop:

Dorothy-2:ra10 grahamellis$ perl evalo.pl
0 >>> Tom
1 >>> Dick
2 >>> Harriet
3 >>> Bob
4 >>> Bob
5 >>> Bob
6 >>> Bob
7 >>> Bob
8 >>> Bob
9 >>> Bob
etc ...


Which is right? Neither - or both - depending upon how you think of it. They're different - and if you're writing a loop which modifies its end condition in any language, you need to be sure how it will behave. Perhaps it would be better for me to suggest to you that loops that dynamically change there end point in this way are best acoided!