You are invited to Log in or Register a free Frihost Account!

Why Perl isn't easy to learn

"...Perl is easy to start learning--and easy to keep learning."
- The PerlFAQ

"We think that Perl is an easy language to learn and use, and we hope to convince you that we're right."
- Programming Perl (Larry Wall, Tom Christiansen, Jon Orwant)

I disagree. Perl is not easy to start learning. And it's not easy to use until your at least past the Beginner level. This is not a Bad Thing (tm). There is no reason why a programming language should be easy to learn. History even seems to indicate that easiness is not a Good Thing when it comes to programming languages (PHP, Basic). Why is Perl not easy to get started with?


In Perl, every expression is evaluated in scalar or list context (well, these are the most important 2 contexts), and the resulting value can be very different and sometimes not what you expected.


($x) = (1,3,2);                 # $x = 1
$y   = (1,3,2);                 # $y = 2
@l = (1,3,2);
$z = @l;                        # $z = 3

The fact that the expression in a return statement is evaluated in the context in which the function is called can easily throw an unsuspecting newcomer off. This prints "b":


sub f() {
   return undef;

print "a" if ($a = f());                # $a = undef, nothing is printed
print "b" if (@b = f());                # @b = (undef) !! prints "b"

List flattening

When a list is evaluated, each element of the list is evaluated in a list context, and the resulting list value is interpolated into the list just as if each individual element were a member of the list, to paraphrase "Programming Perl" (the Camel Book).
What does this mean? Lists within lists are flattened:


my @a = (1,2,3);
my @b = ();
my @c = (4,5,6);
my @d = (@a, @b, @c);

@d now contains the list (1,2,3,4,5,6), and not ((1,2,3), (), (4,5,6)) as you might expect.
List flattening also occurs with arguments to functions and their return values. All function parameters are passed as one single, flat list of scalars, and multiple return values are likewise returned to the caller as one single, flat list of scalars:


sub f {
   my (@first, @second) = @_;
   print "First list: @first, ";
   print "Second list: @second";

my @list1 = (1,2,3);
my @list2 = (2,4,6);
f(@list1, @list2);

This prints "First list: 1 2 3 2 4 6, Second list:".
Now consider a Perl novice who wants to write a functions which substracts the length of the second list it is given from the length of the first. So, given @list1 and @list2, the function should return the value of @list1-@list2.


sub f {
   return @list1-@list2;   

my @list1 = (1,2,3,4);
my @list2 = (2,4);
print f( ... );

But how to get the two arrays into f() without them becoming flattened to one array? A solution obvious to seasoned Perl programmers, like this:


sub f {
   my ($list1, $list2) = @_;
   return @$list1-@$list2;   

my @list1 = (1,2,3,4);
my @list2 = (2,4);
print f(\@list1, \@list2);

isn't exactly, well..., beginner-friendly.

More Than One Way to Write It
Perls motto is TIMTOWTDI, but there is also often more than one way to 'write' (express) the same thing:

(one => 1, two => 2, three => 3)
is the same as
('one', 1, 'two', 2, 'three', 3)

("one", "two", "three")
is the same as
qw|one two three|

display { find Critter "Fred" } 'Height', 'Weight';
if Critter is a class and find a method which returns an object, this is the same as
Critter->find("Fred")->display('Height', 'Weight');

is the same as



print while (<STDIN>)

does the same as


while ($x = <STDIN>) {
      print $x;

Symbol Table and Variable Peculiarities

Global variables and local (lexical) variables are totally diffent things. To really understand the differences you need to know about how they are implemented. For example: global variables are implemented using 'typeglobs', which means you can alias them. Local variables are not.


$a = 4;
$b = 3;

   print ($a+$main::a);                     # prints 8
   my $a = 5;
   print ($a+$main::a);                     # prints 9
   local $b = 1;
   print ($b);                              # prints 1
   print ($main::b);                        # prints 1 too!!


print ($main::b);                                # now prints 3 again!!

Parsing Peculiarities
The way Perl parses a program is sometimes (often?) confusing when you are not an advanced perl hacker (yet).


print (3*4)+2;          # prints 12
print 2+(3*4);          # prints 14

Other Oddities

  • Perls prototypes look like, and often behave like, parameter specifications in other languages. But they are not, and they change the way your function calls are parsed and executed.

  • A lot of functions and operators use the scratchpad variable $_. AFAIK there is no other language with such a functionality.


    # print all input with all letters in uppercase
    while(<STDIN>) {                        # put input lines in $_
       tr/a-z/A-Z/;                    # change string in $_
       print;                          # print $_

  • The relation between the compile phase and interpreter phase is complicated. It is possible (and often practical or necessary) to have the compiler call the interpreter during compiling (for example using BEGIN) or have the interpreter call the compiler at runtime (for example using eval).

  • Methods on objects are just ordinary function with a reference to the object passed in as first parameter. new is just another method. Classes are 'just' packages. Objects are 'just' arbitrary pieces of data, with a blessed reference pointing to them.

  • An assignment expression is a lvalue:


    ($a = 4) = 5;
    print $a;         # prints 5;

  • Autovification. This prints "2":


    print 1 if (defined($a));
    $b = $a->{x};
    print 2 if (defined($a));

  • Using the same notation for different things:
    This leads to confusion by people who are new to a language.
    For example: "use strict" is a compiler pragma, "use CGI" imports the CGI module. <FILE> is a filehandle, <*.txt> returns a list of txt files in the current directory.

  • Endless Flexibility
    Flexibility is nice. And Perl takes this to the extreme. But nice as it may be, flexibility does not necessarally makes a language more transparant and/or easier to master (that's an understatement).


    sub f() {
       return \$x;

    ${ f() } = 3;                   # using a block statement instead of variable name
    print $x;                       # prints '3'

0 blog comments below

© 2005-2011 Frihost, forums powered by phpBB.