Some more reasons that Perl sucks

So Tom did quite a bang-up job of explaining why the switch statement is so retarded in Perl. But there are other reasons that Perl sucks.

The scalar data type is an extremely leaky abstraction
As Joel Spolsky notes in the Law of Leaky Abstractions, you have to understand the theory that an abstraction is, well, abstracting, in order to use it properly because, for any abstraction, there are situations which cause the abstraction to ‘leak’ and reveal the underlying complexity. The better an abstraction is, the further it has to be pushed before it starts to leak.

Testing for equality should not be the kind of Xtr333m action that causes an abstraction to leak, but in Perl, that’s exactly what will happen.

my $foo = function_to_get_input();
if ($foo == 123) {
print "Wooha\n";
}

This seems like a pretty innocent snippet, right? Too bad it will fuck up your day – unless you spend far too much work patching the holes in the abstraction. If function_to_get_input() returned a number, everything’s fine. But if it returned a string, the comparison $foo == 123 will generate a warning, because == expects a number and $foo is a string. So clearly the abstraction is leaky: Perl only provides the scalar data type, because the user ‘doesn’t need to know’ whether the scalar is a number or a string. Unfortunately, the user DOES need to know, because the interpreter is making the user responsible for matching the data types.

Warnings aside, strings in perl also evaluate to 0 in a numeric context – unless they happen to represent a number. This means that == will tell you that 0, “0″, and “My lord, there is talk of cake” are all the same thing. C has NaNs. Perl is written in C. Why does Perl think 0 is a more accurate description of “Mary Poppins is the antichrist, I have proof” than Not a Number?

The string comparison operator, eq, is a bit more generous in its argument coersion; it will automatically convert a number to its string representation. Unfortunately you end up with the same ‘smushing’ effect where 1 and ’1′ are the same thing.

Most scripting languages will have functions like is_numeric() and is_string(), which return 1 if the object is of the listed type and 0 otherwise. But Perl doesn’t have anything like that; in order to get the true representation of a scalar, you’ve got to install a module, written in C, which violates the encapsulation of the scalar to read an internal variable.

The long and short of it is that writing a block like

my $foo = function_to_get_input();
if ($foo eq "Do it") {
print "Wooha\n";
} elsif ($foo == 1) {
print "Blarg\n";
} elsif ($foo eq "1") {
print "My eyes are bleeding help help I can't see\n";
}

ends up being an entirely non-trivial affair.

Input to regular expressions can fuck the interpreter
$foo =~ s/meh/bah/;
works just fine. But suppose we want to replace the right-hand side with the variable $gee. Let’s see what happens:
$foo =~ s/meh/$gee/;
Harmless, right? Sure it is – until $gee gets assigned the value “/” and, you guessed it, the interpreter throws an error and exits. You can solve this with the \Q and \E (start quotation, end quotation) metacharacters, but this will cause a problem – backreferences won’t work. That is to say, if $gee is assigned the value “\$1″ (a literal backslash followed by the numeral one), then the code

$foo = "I know kung fu";
$gee = "\$1";
$foo =~ s/know (.*)/\Q$gee\E/;
print "$foo\n";

will print the line “I $1″ instead of “I kung fu.”

Using evaluation of the right hand as code (adding an e after the regex) can solve this problem, sort of:

$foo = "I know kung fu";
$gee = "\$1";
$foo =~ s/know (.*)/$gee/e;
print "$foo\n";

That gets “I kung fu”. But
$foo = "I know kung fu";
$gee = "\$1";
$foo =~ s/know (.*)/think $gee is awesome/e;
print "$foo\n";

will explode, because the interpreter can evaluate “$1″ as a command, but can’t evaluate “think $1 is awesome” as a command. In order to do that, we’re going to need an extra level of indirection:

$foo = "I know kung fu";
$gee = "\$1";
$foo =~ s/know (.*)/"\"think $gee is awesome\""/ee;
print "$foo\n";

Notice the two e‘s at the end of that regex; they tell Perl to evaluate the righthand side as code, then evaluate the output of that as code, then use that as the substitution pattern.

Perl sucks. And don’t tell me any crap about Perl 6; the Promised Land has been on the horizon for several years now, and PHP and Python and Ruby and a million other languages are way ahead of where Perl was supposed to be. I can’t believe I thought this language was awesome. What a noob.

Author’s note: the original version of this document contained some boneheaded errors. I fixed them. Perl still sucks.

Leave a Reply

You must be logged in to post a comment.