I know, I know, you are probably thinking oh no not again. However, most articles on this subject seem to be very biased towards Python, using flawed arguments that do more to expose the author’s lack of understanding of Perl rather than shedding any new light on the subject. Hopefully this article will do better and help redress the balance.

If you like or even love using Python then please use it. What ever makes you happy, I mean it. A happy developer is usually a much more effective one. Everyone has their own likes and dislikes. However, If you are trying to decide between the two languages or are simply curious then please read on.

Firstly I must state that I am a big fan of Perl 5 and less so of Python, but none the less I have tried to be fair and objective.

Perl

Some of the more common criticisms levelled against Perl are listed below along with my thoughts on the subject:

Sigils

These are special characters that are used in Perl to denote different basic data types (such as scalar, array, hash, function, symbol). These are often cited as white noise that clutters up the program text. This is a perfectly valid criticism.

The reason Perl uses these sigils is because it was born out of a Unix shell scripting environment where the use of such sigils is widespread amongst the other scripting languages that were around at that time (and still are). One can also see other features of the language that owe their existence to these shells.

Another reason is that Perl always knows that a variable is a variable and not something else. If a new reserved word is introduced in Perl then there would be a much reduced risk of a clash with existing code (remember the hassle over C++ introducing the new reserved word and how much ported C code had to be changed to rename variables called new ). Also languages that do not use sigils usually stipulate that variable identifiers have to start with a letter and may only contain alpha-numerics and underscores. Perl’s variable identifiers need not be so restrictive.

Whilst I do agree with this criticism, I have not found the use of sigils to be an issue. Indeed occasionally it has even helped to remind me of what I am dealing with.

Perl Is A Write Once Language

This criticism says far more about the person saying it than it does about Perl. The only reason write once code exists is because the person who wrote it is either inexperienced at writing software, incompetent or lazy.

There are a couple of things to bear in mind. Perl is a very forgiving language. I have often heard people say `I didn’t quite know how to write this code but I typed it in and it just seemed to work’. Perl will bend over backwards to work out what you mean before giving up. The second point is that Perl provides shorthand notations for commonly used idioms that are useful in one line script snippets given on the command line.

However, there are consequences to this. One can throw terrible code at Perl and there is a better than average chance that it might actually work. Also people think that it is clever to use those shorthand notations in proper programs. It is not. In fact it is quite the opposite.

As a consequence of the first point Perl has an inclusive community where people who are not software engineers quite often contribute useful stuff that does the job perfectly well but is less than desirable from a coding point of view. These people may range from scientists and business people to artists. You also get the smarty pants type that likes to show off how awesome they are (invariably ending up doing the opposite).

Writing good maintainable code takes effort, experience and real skill. Just because Perl allows you to write bad code does not mean that you should not write good code. The same can be said of C and C++.

For an example of well written Perl code you can have a look at Completion.pm, which is a module in my mtn-browse application.

Anyone care to tell me what this C program does?

#include <stdio.h> main(t,_,a) char *a; {return!0<t?t<3?main(-79,-13,a+main(-87,1-_, main(-86, 0, a+1 )+a)):1,t<_?main(t+1, _, a ):3,main ( -94, -27+t, a )&&t == 2 ?_<13 ?main ( 2, _+1, "%s %d %d

" ):9:16:t<0?t<-72?main(_, t,"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+\ ,/+#n+,/#;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/\ +k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){n\ l]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#\ n'wk nw' iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c \ ;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;\ #'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/") :t<-50?_==*a ?putchar(a[31]):main(-65,_,a+1):main((*a == '/')+t,_,a\ +1 ):0<t?main ( 2, 2 , "%s"):*a=='/'||main(0,main(-61,*a, "!ek;dc \ i@bK'(q)-[w]*%n+r3#l,{}:

uwloca-O;m .vpbks,fxntdCeghiry"),a+1);}

No? This was the winner of the C obfuscation competition one year.

At the end of the day I would much rather use a programming language that allows me the freedom to do what I want rather than have it constrain me. As they say with Perl ‘There is more than one way to do it’.

Perl 5 I Dead And Perl 6 Has Not Arrived Yet

No Perl 5 is very much alive and is not going to disappear, any more than C or C++ will. It is actively being maintained and enhanced like any other popular and current programming language. Indeed it is taking on board some of the really cool ideas coming out of Perl 6.

Perl 6 will be out for Christmas. Unfortunately no one remembered to tie down exactly which Christmas! Perl 6 is a really bad name for the language as it is not a replacement for Perl 5 as 5 was for 4. It is almost a different language and is regarded as a spin-off or sister language and not a replacement. Unfortunately the name Perl 6 stuck and this has caused quite a lot of unnecessary confusion.

Perl Does Not Do Object Oriented Programming Well

No it is not as nice to write classes in native Perl as in Python. Then again the same would be said of C++ and Java. Python excels at making this stuff simple.

OO was not built into Perl in the same way as it was with Python. However it is still easy to do:

package Organism; sub new { my $class = shift; my $self = {}; $self->{organism} = 1; return bless($self, $class); } package Animal; use base qw(Organism); sub make_sound { my $self = shift; print("$_[0]

"); } package Dog; use base qw(Animal); sub new { my $class = shift; my $self = $class->can("SUPER::new") ? $class->SUPER::new() : {}; $self->{name} = undef; $self->{sex} = undef; $self->{no_of_legs} = 4; $self->{eats} = "meat"; $self->{noise} = "barks"; return bless($self, $class); } sub bark { my $self = shift; $self->make_sound($self->{noise}); }

The above defines a class called Dog that is derived from the Animal class, which in turn is derived from the Organism class. It defines an additional bark() method and its constructor sets up a few new attributes.

One could then use the above class like this:

package main; my $dog = Dog->new(); printf("My dog has %d legs.

", $dog->{no_of_legs}); $dog->bark();

The above is raw Perl code. There are packages one can use that take the tedium out of writing classes in Perl. The best know is called Moose. However, personally I have never found it an issue simply writing classes directly in Perl.

Incidentally Python represents objects in essentially the same way under the skin, dictionaries with meta-data attached to say what class it is.

Perl Does Not Scale For Large Projects

Oh yes it does! I have written ~18,000 line programs in Perl (excluding comments and white space) without any issues of scalability. It supports name spaces, private data and functions, modules, packages etc.

Again this is down to the competence of the people using the language.

In fact one could argue that Perl is more scalable than Python as Python has no true concept of data privacy (just obfuscation).

Perl Does Not Handle Argument Lists Nicely

Granted it does not. But it is not such a big deal:

sub draw_box($$$$) { my ($x, $y, $width, $height) = @_; ... }

One can also do named arguments as well:

sub print_message(@) { my %args = (text => "(null)", colour => "black", row => 0, column => 0, @_); ... } print_message(text => "Hello world", colour => "Yellow");

But no it is not as nice as in Python.

Perl Has No Interpreter Shell

Yes it does. It is its fully fledged very powerful debugger. Simply do perl -d and then Ctrl-D to end the input of program code and you have an interactive Perl interpreter.

Granted this approach does not give you everything but it is certainly enough to try stuff out in.

Perl Is Not Portable

Utter nonsense! It is as portable as Python. Both are available on MS-Windows, MacOSX and assorted Unixes. I have written Perl scripts on one platform that just work on the other.

It is true that Perl’s run time library owes a lot in look and feel to C’s runtime library on Unix but this is more about the style of the API. It still works the same way on MS-Windows. Obviously there are differences between platforms, where certain features of one are not available on the other, but you have packages that help get the best out of that platform as you do with Python.

Where Are Its Batteries?

Sorry I could not resist that! This refers to the batteries included phrase often used in conjunction with Python to denote the fact that it comes with a very feature rich standard library.

Perl does come with a very good standard set of libraries but they are not quite as all-encompassing as those that come with Python. The reason is Perl has CPAN (Comprehensive Perl Archive Network). This is a site offering a vast array of packages for all sorts of useful things. This is quite often referred to as Perl’s Killer App and provides many more modules and libraries. Python currently has nothing as extensive or as mature as CPAN. CPAN modules are also very easy to install. Most can be installed in an automated fashion these days.

In short with Python you are less likely to want to go and download additional libraries, but if you do it may be harder to find what you want. With Perl it is more likely that you will need to download extra stuff but invariably you need look no further than CPAN.

Perl’s Libraries Are Ugly To Use

This is usually said in reference to the fact that Perl’s libraries were only procedural and used clunky global file handles. This used to be the case, and it is still supported for backward compatibility reasons, but there are now OO interfaces for most libraries and global file handles are no longer necessary.

For example to open a file and display its contents one could do:

use IO::File; sub cat() { my $line; my $file = IO::File->new("/etc/hosts", "r"); while($line = $file->getline()) { print($line); } } cat();

Notice how I did not close the file. I could have used $file->close() but I do not have to because when $file goes out of scope the file is automatically closed by $file ‘s destructor.

Python

When I went on the Python 3 course I was looking forward to learning a new language and seeing what all the fuss was about. Whilst there were many times that I thought `hmm that is nice’, time and time again I caught myself thinking `oh no I can’t believe it does or doesn’t do that’. It seemed that every bit of enthusiasm was knocked back by an even bigger concern or disappointment.

Basically I found Python to be a very nice idea poorly thought out and executed. The initial start-up project for Python could have done with someone more experienced in language design.

I have written tens of thousands of lines of Python code and have done some meta class programming so I have not just dabbled but actually used it in earnest for work.

Some of my observations, both good and bad, are listed below:

Batteries Included

One of best things about Python is that it comes with a very comprehensive standard library. Most of the time you will not need to go looking elsewhere for something. Probably the only thing I can think of is bindings to a decent graphics library like Gtk2 or QT4. However there is no Python equivalent of CPAN in both its size and maturity.

Cleaner Syntax

Regardless of some points raised later. There is no denying that Python code does look cleaner. Whilst it does make use of sigils, they are far fewer in type and are mainly concerned with data obfuscation.

Many Different Versions

Python is still suffering from that initial churn that you get with a relatively new language. This is not a fault of Python as this happens with any newish language. It takes time for things to settle, solidify and calm down. But on projects using Python you constantly hear the phrase, `oh you must use version x or later’. That just does not happen with Perl.

In my experience Perl scripts just tend to work regardless of the version of Perl being used (assuming the version 5 family). We have used Perl on RedHat 9 up to the latest Linux with little to no issues. However one Python network component got rewritten in C to avoid the constant issues with Python versions natively installed on the machines (being a testing environment we did not want to mess around with the systems by putting later versions of Python on them).

Just something to bear in mind. This is getting less of an issue as time goes on.

Syntactic White Space

Oddly this is not a show stopper for me as for some people. However, syntactic white space is a bad idea. There are good reasons why nearly all popular programming languages do not use it.

Things not good about this include:

It makes the language brittle. Indentation can easily get mangled in emails, on wikis or when editing source code in a different editor. Even cutting and pasting code can be an issue where the pasted code is inadvertently left at the wrong indentation level. I had more indentation issues in three months of programming in Python than I had with missing braces in twenty years of C/C++ programming.

You can limit the syntax. What about having a do-while loop in Python? No can do unless you want some awful kludge.

It is often difficult to see how much you need to come out of some deeply nested code, especially if you are coming out a couple of levels in one go. Syntax aware editors cannot help you as they can in say C or Perl. Also curly braces act as a very useful visual clue as to when some nested block finishes (remember that statements wrapped over multiple lines will typically have their continuation lines indented, thus mucking up any nice visual clues as to nesting and structure).

Tabs vs spaces and misguided attempts at redefining the size of tabs within editors! Enough said on that one.

Lastly, I read somewhere on a Python site that the initial reason for using syntactic white space was because it was seen as a challenge. Perceived wisdom in language design circles said that no high level and powerful language could successfully make use of syntactic white space. Unfortunately I now cannot find the reference. However, if true, one should always have a better reason for introducing a language feature than because it has not successfully been done before. It has to be of use and make the language better.

Unreliable Destructors

In my view an OO language that does not call an object’s destructor as soon as that object goes out of scope is not a language I wish to use. This is such a useful feature of C++ and Perl and allows you to do some very powerful scope based operations. For example, scope based mutex locking that will automatically unlock should an exception be thrown.

In Python using destructors is frowned upon. I did not understand this at first as they seemed to work fine. Indeed any discussions as to where they may not work revolved around edge cases that I was more than prepared to accept (apart from the exception handling scenario, but even that can be handled).

Then the answer came to me in the form of Jython (a Python interpreter written in Java). In C Python (the main Python interpreter written in C), destructors behave as one would expect in a reference counting system, all was good. However in Jython it simply uses Java’s garbage collector and hence Jython destructors get the same lame and useless behaviour as that seen in Java.

Nothing stipulates the precise behaviour of any garbage collector that may be used in the implementation of a Python interpreter. Thus C Python happens to use reference counting at the moment, but this may change in the future. Also Jython can get away with simply using Java’s garbage collector. Indeed there is even some talk of putting a Java style garbage collector into C Python.

But why is this so important? When the memory gets freed up does not matter? No it does not, in fact interpreters can often make more efficient use of their heap by not freeing up memory straight away. However, it is not about memory, it is about other operations that may need to be done like closing files, dropping network connections or closing databases. Being able to do this in a destructor means that these things automatically get cleaned up when exceptions get thrown or you simply return early from a routine.

One can also do neat tricks like scope based locking. Indeed there is a design pattern in C++ where a library developer can enforce that you can only take out a lock as a scope based lock, thus drastically reducing the likelihood of deadlocks occurring due to badly written code.

For a specific article discussing the benefits of what is commonly referred to as RAII please look here.

In Python 2.5 they introduced the with clause. This does help. However this is nowhere near as elegant as RAII. Firstly you have to remember to use with , rather than simply enforcing policy in constructors and destructors (that incur no extra effort on the users of those classes) and secondly this introduces more stuff that is not necessary if RAII were used ( __enter__ and __exit__ operators and the with clause itself).

Syntax

Python has made some weird and ugly syntax choices. A lot of languages get their syntax from C. C uses a nice clean syntax that can cope with multi-line if clauses.

Python makes use of the colon to denote the end of certain parts of its syntax. This is ugly as it shouts out at you and there is no need for it if a bit more thought had gone into it. I keep thinking of labels or name separators.

This is the one ugly thing about Python. I know it is probably a personal pet hate, but there you go.

As for the rest of it some things are different, I miss the ++ and -- operators but I like how their for loops work and how classes are defined.

Another thing that does bug me a little is when everything is supposed to be OO, why are there procedural ways of doing things? For example, if you want to find out the length of a list you do not do myList.length() but len(MyList) . If one wishes to enforce a standard way of getting the length of something then one could always put that into a style or API guide.

Non-Standard Scoping

Even if Jython was just someone’s idea of a bad joke and destructors were specifically designed to always behave like they currently do in C Python then Python’s scoping rules would shoot you in the foot!

Once a variable has come into existence it remains until the enclosing function exits and not when the enclosing block terminates. So bang goes any idea of scope based locking done by mere class definitions, constructors and destructors.

I wonder how many people coming to Python have been caught out by this?

I know you could use the with clause to deal with cases where this was an issue, but as I said before, this is an inelegant solution.

Closures And Anonymous Functions

Closures seem to work in a rather clunky way. However they do work. I have found the need to use container objects rather than scalars, certainly if you want to pass anything back to the outer scope.

Anonymous or Lambda functions are also limited in their ability. However one can declare a named function in an inner scope and use that instead.

In Perl anonymous functions have the same capabilities as named ones. It is especially nice to use them inline inside function calls for registering small one-off callback functions in a GUI program.

No Data Privacy

Python has no concept of data privacy, only obfuscation.

Python has two levels of obfuscation:

Identifiers that start with a single underscore denote a weak internal use only entity. It is really a warning this is actually private convention. In fact I think the only case where any attention is paid to the single underscore is when they are ignored during a from ... import * . However, such variables can still be accessed by doing <Package>._ .

. However, such variables can still be accessed by doing . Identifiers that start with two underscores denote something that is private to a class and are actually altered to have their containing class prepended onto the front of the identifier. This is really meant as a means of making sure that attributes within a class do not interfere with other attributes in base classes. However, again one can simply prepend the class name onto the front of the identifier to get at it.

Python is quite open about how the above works and the intention of the double underscore. Neither enforces privacy.

On the other hand Perl does support privacy. Anything declared as a my variable at the file scope level is only accessible from within that file, period. The only way Perl code can access another file’s my variables is by modifying that file to make them non-local or to provide accessor functions.

Routines can also be made local to a file with something like:

my $private_func = sub { ... } ... &$private_func();

Although this is less common.

No Variable Declarations

In Python variables simply come into existence when you assign something to them, there is no concept of explicit declaration.

This is such a pain! Firstly let us not forget the obvious question. What happens if you mistype the name of a variable that already exists? Well if you are assigning something to it then that assignment gets lost in another variable, if you are reading from it you get a run time exception. Grim.

Another issue is that this leads to ambiguity when you have multiple scopes. So instead of having one simple var keyword, Python has the global and nonlocal keywords (the latter is only available in Python 3).

More Errors Are Detected At Run Time Than Is Desirable

Certain mistakes in the code are only detected at run time and not at compile time. The best example of what I mean is the case of a mistyped variable. If you accidentally reference a non-existent variable, because you mistyped the name, you do not get a compile time error as you would expect, but rather the program runs normally and then should that offending piece of code be executed you get a run time exception.

This is grim. Basically you have to make sure that all your code has been executed before you can say that the program is even semantically correct.

Of course with dynamically typed languages like Perl and Python, there is a tendency towards certain things being detected at execution time that would otherwise have been detected at compile time with say C or C++. For example, type mismatches are only detected when the offending code is actually run. But this issue is much more noticeable in Python.

Some people say that this is normal behaviour for an interpreter. However this is completely incorrect. Whether you use an interpreter or a compiler is irrelevant, they are just the means by which the code is run. It makes no difference as to what errors can be picked up before execution of the code commences.

What does influence this is the design of the language. For example, by not having variable declarations, Python cannot detect semantic errors like assigning to variables with misspelt names. Another example is to do with operators. Perl has operators dedicated to string handling where Python uses generic arithmetic operators. One can argue the merits of using a `.’ operator for string concatenation versus `+’ (some would argue that using `+’ is wrong since concatenation is not commutative), but one fact is undeniable, using `.’ removes any ambiguity. Thus Perl always knows when to convert something into a string or a number. Python does not. Issues like these are why Python reports such things as run time exceptions rather than silently converting the data type for you.

Data Typing

Python is highly typed. This may sound like a good idea. However you have some of pedantic pain that comes with tight data typing without some of the benefits.

For example, as mentioned previously, Python can only raise an exception when adding a number and a string together rather than silently converting the number. Ok you would have to do the conversion in C or C++ but at least it would fail during compilation if you skipped the conversion step. So what about the advantages? Do you get function overloading based upon parameter type? No. Can you stipulate the type of a parameter in a function declaration? No, this has to be coded within the function.

For it to work properly you would really have to go all the way and be able to declare typed variables and parameters up front and explicitly. I.e. ditch dynamic typing altogether, or at least have separate categories of operator for basic types.

Documentation

The documentation that comes with Python is generally well laid out and it is pretty easy to find the subject matter that you are after. However I have found that it quite often does not go into enough detail. There is an awful lot to cover with Python and so hopefully in time this will get better.

Conclusion

Despite its often cited shortcomings, Perl is a language that I have steadily come to respect and to be impressed by. I have found it a delight to use and quite intuitive and forgiving. I can get things done reliably and quickly and it is great fun doing it. I can concentrate on coming up with a solution to a problem rather than getting bogged down with the very low-level stuff as one can do in C. I have also been impressed with its speed and robustness.

Largely the same can be said of Python. However, when learning the language, both on a course and then using it for real, any enthusiasm for the language was invariably quashed by some fundamental flaw or oversight. I feel it is a language that had true potential to be one of the all time greats if it were not for some ill thought out design and implementation details. Which is a great pity as Python started from a clean slate and so could have avoided most if not all of these unnecessary pitfalls.

If you are used to the traditional shell scripting languages in use on Unix then once you start using Perl you will never look back.

However if you are coming from a completely different background and do not find the points I raised against Python to be of huge concern then you might want to give Python a go. There are a lot of good and novel things about this language.

One thing I would say is that if you are looking to learn how to program then be aware that Python does have a unique syntax and style, not sharing that much with other languages. Another language you may wish to consider in this case would be Java.

At the end of the day, you will not go far wrong with either language. The most likely thing is that the job will dictate what language you use.

What ever you decide, enjoy it and have fun :-).