Tuesday, April 18, 2006

Perl: Comparisons are odious

Here's a little bug that I discovered in a Perl script today. It involves a confusion between string comparison operator cmp, and the numerical comparison operator <=>. Here's a sample code which demonstrates the problem:


$FRUIT{0} = [1, 'apple'];
$FRUIT{1} = [2, 'banana'];
$FRUIT{2} = [10, 'pear'];

foreach $id (sort { $FRUIT{$a}->[0] <=> $FRUIT{$b}->[0] } keys %FRUIT)
{
   ( $id, $name ) = @{$FRUIT{$id}};
   print $id . " [" . $name . "]\n";
}
print "===\n";
foreach $id (sort { $FRUIT{$a}->[0] cmp $FRUIT{$b}->[0] } keys %FRUIT)
{
   ( $id, $name ) = @{$FRUIT{$id}};
   print $id . " [" . $name . "]\n";
}


The output looks like this:

1 [apple]
2 [banana]
10 [pear]
===
1 [apple]
10 [pear]
2 [banana]


The operator cmp is a string comparator. It sorts the numbers "1", "2", etc. differently than you might expect. "10" is less than "2" when doing string comparisons.

This is the kind of bug you face with loosely typed languages like Perl.

0 Comments:

Post a Comment

<< Home