PerlLoopIncrement

Recently I came across a curious bug in a perl script (naturally I found the bug via code review). Here's a code snippet of what got me thinking:

for $i (1..4)
{
  # do something
  $i++;
}

Wait, what? I knew from using the script previously that it definitely executed the loop four times. So what's up with that extra $i++ in there? Shouldn't that cause the loop to only be run twice? I tried some sample code to figure it out:

for $i (1..4)
{
  print "before: $i\n";
  $i++;
  print "after:  $i\n";
}

which results in:

before: 1
after:  2
before: 2
after:  3
before: 3
after:  4
before: 4
after:  5

that demonstrates $i was being incremented by the $i++, but that was being thrown away on each iteration of the loop.

Compare to this behavior in a traditional for loop, which is what I expected:

for ($i=1;$i<5;$i++)
{
  print "before: $i\n";
  $i++;
  print "after:  $i\n";
}

which results in:

before: 1
after:  2
before: 3
after:  4

that demonstrates $i is being incremented by the $i++ and that incremented value is the starting value for the next iteration of the loop. Thus the loop only gets executed twice, as expected.

I think this behavior has to do with how the range operator in the first example works. It evaluates to the list 1,2,3,4, and the number of iterations of the loop is then fixed. In this case it really is a foreach loop (although I know that for and foreach are the same thing in Perl).

However, the second example is a true for loop so that incrementing of $i inside the loop is taken into account.

I welcome a better explanation of this behavior if anyone has one. Does the precise answer have something to do with variable scope?

Also you might wonder where this weird construct came from. I think I know: the original author started with a while loop, like this:

while($i < 5)
{
  # do something
  $i++;
}

but he then switched to a for loop and forgot to remove the extra increment operator for $i.

So anyway, that's my observation of an odd perl bug that made me scratch my head for a moment. Also do note this is another great reason why sysadmins should do code review.


CategoryGeekStuff

CategoryPerl

CategoryBlog



Our Founder
ToolboxClick to hide/show