Everything2
Near Matches
Ignore Exact
Everything2

Why Perl sucks

(idea) by William G. Davis (1.6 mon) (print)  ?  1 C!Fri Feb 06 2004 at 10:02:37

Maybe "sucks" is too harsh a word, but in the convention of "Why C sucks" and "Why C++ sucks," it's probably an appropriate title.

First, let me say that Perl is by far my favorite programming language. I love it's power, I love its elegance, and most of all, I love its expressiveness. However, Perl is certainly not without its flaws.

The tone of this writeup isn't meant to be negative. I think we can benefit from acknowledging the flaws of the programming languages we like, especially the really popular ones, so we can ensure those flaws never make their way into other languages.

So with that, here's my informal list of problems with Perl:

  1. No Object Inheritance.
  2. Inheritance in Perl is implemented via the @ISA array (pronounced "is a", as in "this is a problem"), which allows you to call methods from one package on a reference blessed into another package. For example, if SomeClass has SomeOtherClass in its global @ISA array, then you can call any method from SomeOtherClass directly on references blessed into SomeClass.

    Unfortunately, there's no real way to inherit objects from other classes in Perl, only their methods. The workaround commonly used is, in the constructor method of the class that wants to inherit, call the constructor of the class you want to inherit from to get the object, add your own hash key/value pairs to it as needed, then bless the object into your class:

    package SomeClass;
    use SomeOtherClass;
    
    @ISA = 'SomeOtherClass';
    
    sub new {
    	my $class = shift;
    
    	# create a new SomeOtherClass object:
    	my $self = $class->SUPER::new;
    
    	# mess with it:
    	$self->{'_something'} = 1;
    	$self->{'_something_else'} = 2;
    
    	# now bless it into SomeClass:
    	bless($self, $class);
    	return $self;
    }
    
    1;
    

    The problem with this is that it violates the laws of encapsulation and abstraction: you need to know the internals of the object you're inheriting and then you go right ahead and mess with its members directly. You can use containment or declare global variables in one package, write routines to manipulate those variables, then inherit those routines from that class... but still.

    With the myriad of object-oriented modules on CPAN it's easy to forget that Perl was originally designed as a purely procedural programming language. Things like this make those roots painfully clear; OO in Perl is really nothing more than blessed references and a piece of syntactic sugar.

  3. Reference Counting.
  4. Perl uses reference counting for garbage collection, a simple form of memory management that ensures timely destruction of discarded resources. Every scalar, array, hash, whatever has a reference count in it that starts out at one. Every time that variable is referenced, its reference count is incremented. When the reference is removed, the count is decremented. Eventually, when the last reference is exhausted, and the count reaches zero, and the memory used by the variable is reclaimed.

    The problem arises when you have two variables that refer to one another, like a parent hash and child hash that both contain references to each another. Since neither one's count can be decrement to zero until the final reference is removed, one can't be freed until the other is, and they both end up just hanging around taking up space. This is what's known as a "circular reference." (See this for more information: http://www.perl.com/pub/a/2002/08/07/proxyobject.html)

    This means that it's surprisingly easy to leak memory in Perl. Many budding Perl hackers do this by accident. They think, Gee, wouldn't it be useful for this object to contain a reference to its parent, and vice versa, and viola, memory leak.

    Perl is certainly not alone in going with reference counting. VB used it, Python still uses it, and so does PHP.

    Maybe the biggest problem with reference counting is the burden it places on extension writers. It forces them to scatter calls to SvREFCNT_inc() and SvREFCNT_dec() all throughout their code, making sure each SvREFCNT_inc() has a corresponding SvREFCNT_dec(). Which brings me to my next gripe...

  5. Unintuitive API.
  6. The Perl C API is interesting. First, there's no visible naming convention. Some routine names are mixed case, like newSViv(), while others have underscores in them, like av_push(), while others still have some odd combination, like newRV_noinc(). Many variables and structure members have terse, sometimes misleading names, like "cur" for length and "len" for size.

    The API is also full of macros, many of which aren't documented in perlapi or any other man page, like HvKEYS().

    And to make things even more fun, for the functions that actually are documented it often doesn't say whether or not they modify the ref count of their arguments.

  7. Unintuitive Behavior of Arrays/Lists in Scalar Context.
  8. I really don't like having to write code with more parentheses like this:

    my ($first_field) = split(/\t/, $tab_delimited_fields);

    to stop a list or array returned from some function from behaving badly.

    In Perl, arrays return their length when used in scalar context and list literals (e.g., "(70, 80, 90)" in source code) return their last element. Ok, first, why on earth is there any difference between an array and a list literal to begin with? Second, when and why would I ever put a list literal in scalar context just to get its last element?

    I think it would have been far better if both arrays and list literals behaved the exact same way and returned their first element when called in scalar context instead of their length or last element. Then you could write code like this:

    my $email_address = $input =~ /(\S+\@\S+)/;

    and it would work.

    How, you ask, would one get the length of an array then? Well, why not with the length() function? Many newbies assume it does that anyway.

  9. Formats.
  10. Formats in Perl were supposedly the "Report" part of Practical Extraction and Report Language--of course "Perl" isn't an acronym anymore and when, honestly, can you last remember using formats? In fact, off the top of your head, can you even remember how to use formats correctly?

    This large, largely ignored part of Perl sucks for a variety of reasons.

    First, the format definition syntax itself is clunky (how do about 20 or so "<" characters back-to-back sound?), global (you have to stick it in a big, period terminated block somewhere--probably at the bottom of your program), and completely different from normal Perl syntax (making you much more likely to forget it, of course, especially since you never use it).

    Second, doing anything significant with formats results in verbosity, often requiring use of the select() function and playing around with $^ before calling write(), forcing you to use three statements to accomplish what should really only take one. (Four statements if you count resetting select().)

    Third, anything a format can do, printf() and its sprintf() counterpart can usually do too. Even though the format syntax is arguably more flexible than printf(), using multiple printf()s usually gets the job done, and in a shorter, clearer way, no less.

    Perhaps the worst part of all of this is that write() is stuck printing nonexistent formats instead of doing fixed-length IO like read(), its English language opposite:

    "Note that write is *not* the opposite of 'read'. Unfortunately"--(perldoc -f write).

  11. No Constants or Macros.
  12. This could really be two separate gripes, but Perl has no simple way to declare variables as constants or define macros as alternative to scattering magic numbers throughout source code.

    Yes, Perl has a "constant" pragma that purports to do both, but that's really just a hack; a clever, elegant hack, but a hack nevertheless:

    use constant PORT => 80;

    PORT can now be used as an rvalue in an assignment as though it were some sort of constant, and any attempt to assign something to it will result in a fatal error. But you see, PORT really isn't a constant, it's just a subroutine prototyped to take no arguments. You can still overwrite it using a sub declaration or with "use sub" or by messing around with the symbol table directly. More importantly, one purpose of constants is efficiency; making things easier on the compiler by promissing not to assign something to a variable again. Here, rather than any meager benefit, perl, the interpreter, takes an obscene performance hit.

  13. No Type Information.
  14. In Perl, scalars can contain either stuff or references to stuff. Unfortunately, Perl provides no operators to find out what kind of "stuff" a scalar contains, only what kind of references. This makes, for example, finding out if a scalar contains a numeric value suitable for performing arithmetic on surprisingly difficult. Yes, I understand we Perl hackers are to think of numbers and strings as being interchangeable, but it comes up, and it's absurd to have to resort to using the regex engine to find out:

    print "Not a number!" unless ($thing =~ /^\d+$/);

    Of course, the above pattern match doesn't really work, as numbers can contain other characters like "+", "-", or "." to denote sign, fractional parts, or exponents.

    Even the ctype.h functions would be more helpful than nothing.

    This is all the more annoying because Perl apparently has a pretty good idea of what type of value an SV (a C typedef used for scalar values) holds based on its "flags" member, and can easily convert from one to the other as needed.

  15. Autovivification.
  16. Hash key/value pairs autovivify in Perl. That means you can specify a new key like "autovived" and it pops into existance:

     my %hash = (key1 => 'value1', key2 => 'value2');
    
     $hash{autovived} = 1;
    

    That also means you can mistype a key and it will pop into existence too, without so much as a warning. This isn't a big problem when you use hashes as dictionaries because your keys often come from somewhere else, but when you use a hash as a structure or object, it causes problems:

     $self = {
     	name => undef,
     	age  => undef
    
     ...
    
     sub name {
     	my $self = shift;
    
     	$self->{Name} = shift if @_;
    
     	return $self->{name};
     }
    

    When I use hashes as objects, I always define and initialize each element of the hash inside of the constructor method to something, "undef" if nothing else. What I wouldn't give for a "static" keyword to prevent new elements from being added to the hash after it's initialized:

     static my $self = {
     	name => undef,
     	age  => undef
    
     ...
    
     $self->{Name} = shift; # fatal error
    

Other, more minor gripes come to mind, including no chop() equivalent for the front of a string, no chaining of the -x file test operators (you have to do "-e $filename && -T $filename && -w $filename" instead of "-e -T -w $filename" or "-eTw $filename"), bizarre calling conventions for binmode(), unstable signals, misleading names like local(), and no sizeof() function.

This 16-year-old language has been steadily putting on weight for some time. Many aspects of it have become unintuitive, inefficient, or just plain ugly. The internals are unmanageable, and adding new features without breaking old ones is becoming exceedingly difficult

Perl 6 is an attempt by the Perl community to fix many of these problems. A real object system will be added, reference counting will be gone, sigils ($, @, %) will be more intuitive, and whole new bag of features will be added.

This top-to-bottom rewrite of the language is still a long way from being finished, but I, along with many others, eagerly await it. Until then, I guess I'll keep using Perl 5 to get most of my work done.

Compare with: Why Perl Doesn't Suck.


printable version
chaos

Why C sucks Perl Perl: Converting an integer or float to currency Slithering Perl Horrors
Perl Core Language Why C++ doesn't suck How to hack the installation of Tomcat Just another perl hacker
Perl: Objects NaN Perl Line Noise Janet Jackson
Sv Dow Jones Global Titans 50 buffered IO scalar context
I don't like the looks of those teenagers Object Oriented Programming Simple statement modifiers in Perl 1337
Everything Sucks PHP Perl 6 Ruby
Y'know, if you login, you can write something here. You can also Create a New User if you don't already have an account.
  Epicenter
Login:
Password

password reminder
Create a New User
  • Random Node
  • E2 Scratch Pad
  • [ * ] Read Em Or Weep

    server time
    Wednesday, June 6, 2007 at 7:31:19

    Random Nodes
    Just another sprinkling of indeterminacy
    host
    Leonymus
    It's not me, it's you
    Faecelex
    Etruria
    Workbench
    Women Who Run With the Wolves
    parodist
    How to Cook Everything
    Global Hawk
    Naileress
    Strategic Arms Limitation Treaty (SALT II)
    New Writeups
    locke baron
    Common Desktop Environment(idea)
    Jack
    Dynamic Ribbon Device(thing)
    kanoodle
    DAW Books(thing)
    Cockroach.
    Why is there no Nobel Prize in Mathematics?(idea)
    kanoodle
    Donald A. Wollheim(person)
    borgo
    Concord Principles(person)
    baffo
    STREP(thing)
    kobold
    Christina Milian(person)
    kanoodle
    A. Merritt(person)
    not_crazy_yet
    In case of accidental death, back up your state vector regularly!(idea)
    locke baron
    Sun Ultra 10(thing)
    Heisenberg
    Editor Log: June 2007(person)
    santo
    No need to yell, I can hear your thoughts.(fiction)
    locke baron
    XVR-1000(thing)
    locke baron
    XVR-500(thing)
    Vitals
    [ * ] Maintenance

    [ * ] Noding Information

    [ * ] Noding Utilities

    [ * ] Lists

    [ * ] Miscellaneous


    Donation Box
    E2 Merchandise
    Personal Links
    You must log in first.
    This page courtesy of The Everything Development Company