Here in the Perl echo chamber, there's a lot of talk about advocacy and getting people to use Perl and whether Perl is more popular in the job market than PHP, but I think most of that is just wind in sails. We talk and talk and talk but when it gets down to it, people don't use Perl because it's bigger in the job market, or because of a well-argued thread on Slashdot. People use Perl because the power of Perl makes their lives easier.

Back on the 17th, I posted that Perl would be allowed in the Microsoft Scripting Games. Now, I'm no friend of the "scripting" moniker, but I was glad it was allowed in and thought maybe there would be some good visibility for the power of Perl.

Then I saw the results.

Event 2 in the competition was to read in a text file of comma-separated values of ice skating scores, drop the high & low scores from each skater, and show the top three skaters and their average scores. Trivial for Perl, right? The solution that Microsoft posted, however, was effectively a VBScript script translated to a Perl program (by their own admission).

Here's the solution they posted.

%dictionary = ();
open (SkaterScores, "C:\Scripts\Skaters.txt");
@arrSkaters = <SkaterScores>;
close (SkaterScores);
foreach $strSkater (@arrSkaters)
{
$intTotal = 0;
@arrScores = split(",",$strSkater);
$strName = @arrScores[0];
@arrScoresOnly = (@arrScores[1],@arrScores[2],
@arrScores[3],@arrScores[4],
@arrScores[5],@arrScores[6],@arrScores[7]);
@arrScoresOnly = sort({$a  $b} @arrScoresOnly);
$intTotal = @arrScoresOnly[1] + @arrScoresOnly[2] +
@arrScoresOnly[3] + @arrScoresOnly[4] +
@arrScoresOnly[5];
$dblAverage = $intTotal / 5;
$dictionary{$strName} = $dblAverage;
}
$i = 0;
foreach (sort {$dictionary{$b}  $dictionary{$a} }
keys %dictionary)
{
$i++;
print "$_, $dictionary{$_}n";
if ($i == 3) {exit}
}

Just dreadful. Among the atrocities: Stringing together list elements with plus signs to get a sum; Hardcoded array indexes; Hungarian notation prefixes of variables, in addition to the Perl sigils; breaking out of a loop after three records are shown, rather than starting with a list of the top three. It's just not good idiomatic Perl code.

Perl's arrays and hashes are powerful, and underused here. Perl arrays are treated like C arrays.

In a few minutes, I had put together the following program which is shorter and clearer because it takes advantages of Perl's strengths.

use warnings;
use strict;
my %averages;
open( my $SCORES, '<', 'c:/scripts/skaters.txt' )
or die "Can't open score file: $!n";
while ( <$SCORES> ) {
chomp;
my ($name,@scores) = split ',';
@scores = sort @scores;
# Drop high & low scores
pop @scores;
shift @scores;
my $total;
$total += $_ for @scores;
$averages{$name} = $total/scalar @scores;
}
close $SCORES;
my @names_by_score =
sort {$averages{$b}  $averages{$a}} keys %averages;
for my $name ( @names_by_score[0..2] ) {
print "$name: $averages{$name}n";
}

(I'll admit I haven't tested it against their sample data because their sample data is only available in a self-extracting .EXE, which is a bummer for us non-Windows folks, no?)

After I wrote my solution, I noticed that they have an Experts Page that includes links to solutions offered by Jan Dubois of ActiveState. No surprise, Jan's solution is exemplary Perl, and I'm glad that Microsoft provides it. My frothing subsided a bit after discovering this.

Rather than arguing with non-Perl people about which language is better, let's show them. Even more, let's show the people who think that Perl is only a scripting language, only for web sites, or can't be deciphered that Perl will make their lives easier if they'd only open their Swiss Army knives beyond the first blade.