In general, subroutines should receive data, process that data, and then output something. There are some exceptions. In void context, we have no output. In the case of information retrieval from a fixed source there may not be any input. An error logging routine might have input and output but no processing.

Good subroutines only affect and are affected by their own environment. If events exterior to the subroutine affect it, you have probably done something wrong. Here's an example of a poorly written subroutine. foo() is using $bar. $bar has not been passed to it. Remember that a well written subroutine has data passed to it. Good subroutines only affect and are affected by their own environment. Deleting the $bar variable outside this subroutine affects the subroutine.

  1. sub foo {
  2.     return $bar;
  3. }

(more...) is a module included in the standard perl distribution. It is the most commonly used module for writing perl scripts that interact with the web.

I run across these mistakes a lot when reviewing beginner perl code. The first mistake has to do with the dual nature of perl modules. A perl module can be accessed either as a function-oriented module or as a object-oriented module or by both methods. allows both. Under the hood, that makes for some messy looking code. In practice, we find a lot of bloated code. Normally, we would use either the function oriented or the OO version, not both.Here are a few of the most common errors I see.


The author of this module chose to use some file scoped variables in a module. This effectively created some global variables used outside the sub. This is not the recommended way to write a subroutine, but I needed an example and this one was handy. :)

  1. my $htmltree;
  2. my $node;
  3. my @prevnodes;
  4. my $htmloutput;
  6. sub start {
  7.     my $tagname = shift;
  8.     my $attr = shift;
  9.     my $newnode = {};
  11.     $newnode->{tag} = $tagname;
  12.     foreach my $key(keys %{$attr}) {
  13.         $newnode->{$key} = $attr->{$key};
  14.     }
  15.     $newnode->{content} = [];
  16.     push @prevnodes, $node;
  17.     push @{$node}, $newnode;
  18.     $node = $newnode->{content};
  19. }


Opening files in perl is a fairly easy task. Here are the basic file opens. Do not use them in production code.

  1. my $file = 'foo.txt';
  3. # open for read
  4. open FH, ">$file";
  6. # open for write
  7. open FH, ">$file";
  9. # open for append
  10. open FH, ">>$file";


There is an old saying amongst carpenters. Measure twice, cut once. This cuts down on materials. The same is true of typing for Perl programmers. Read more, type less. Okay, that doesn't have the same ring, but reading the documentation before writing your script does make sense.

I came across a script recently where a beginner programmer had obviously decided that typing was easier than reading. Here's an excerpt. The author needs to start a really wide table, but won't end it for a while yet.

  1. use CGI qw/:standard/;
  3. print "<table border = 1>",th,"day",td,"Date",td,"Time In",td,"Break Start",td,"Break End",td,"Time Out",td,"Evening In",td,"Evening Out",td,"flex hours",td,"flex bal",td,"lieu",td,"adjustment",td,"lieu adjustment",td,"type";


This is an excerpt of an answer I gave on an Excel VBA mailing list. The original poster asked if I could explain my solution.

Let's look at a single solution not involving a sub routine call. We'll use the Combo Box control named CboMonth. Here's the submitted method with some white space added for us poor human readers. :)

Visual Basic:
  1. With CboMonth
  3.     .AddItem "1"
  4.     .AddItem "2"
  5.     .AddItem "3"
  6.     .AddItem "4"
  7.     .AddItem "5"
  8.     .AddItem "6"
  9.     .AddItem "7"
  10.     .AddItem "8"
  11.     .AddItem "9"
  12.     .AddItem "10"
  13.     .AddItem "11"
  14.     .AddItem "12"
  16. End With


Many times when writing code, a beginner will ask the language to perform an operation and receive an unusual result. While possible, it is highly unlikely that a beginner will find a bug in perl, JavaScript, etc. Programmers must be humble. The fault ususally lies with us.

Chances are we are asking the programming language to do what we mean instead of telling it what we really want to do. Some languages have logic builin that will try to guess when something might go either way, but we shouldn't depend on this.

Here's an example

  1. $time = "10:10:00";
  2. $other_time = "10:10:40";
  3. print $time - $other_time;

No web programming language will return 40 seconds as the answer without extra work.

The programming language does what I want (DWIW), when I was hoping it would do what I mean (DWIM). The next time you don't get a desired result, make certain you are using DWIW.

Sometimes you just have to peek. Whether it's baking brownies, an overheated engine, or a data structure, sometimes you just have to look under the hood. When programming in perl you need to dump the contents of your data structure to see what's there.

  1. #!/usr/bin/perl
  3. use strict;
  4. use warnings;
  5. use Data::Dumper 'Dumper';
  7. my @sirsi_array = (
  8.     '671|Psychophysiology|PPSY',
  9.     '671|Psychophysiology|',
  10.     '675|Notes and queries|PENG',
  11.     '675|Notes and queries|',
  12.     '675|Notes and queries|',
  13.     '676|The Journal of general psychology|',
  14.     '681|Greece & Rome|PHIS',
  15.     '681|Greece & Rome|',
  16.     '681|Greece & Rome|',
  17. );
  19. my %sirsi;
  20. foreach my $item ( @sirsi_array ) {
  21.     my( $key, $title, $data ) = split /|/, $item;
  22.     push @{ $sirsi{ $key } }, [ $key, $title, ];
  23. }
  25. print Dumper \%sirsi;
  27. __END__


This may seem trivial, but I believe how we organize programs is directly influenced by how we think. Perhaps learning to better organize code will lead to better organized, more efficient thinking.

  1. #!/usr/local/bin/perl -w
  2. use strict;
  3. open (FH,"/usr/local/bin/perld/derektapes") or die "cannot open FH: $!\n";
  4. my $w_param="-w ";
  5. my $tick="'";
  6. my $b_param="barcode=";
  7. my $or_string=" or ";
  8. chomp ( my @a = <fh>);
  10. #       $a[$i]=$_;
  11. #       $i++;
  12. #       print map {$_, "\n"} @a;
  14.         print $w_param$tick;
  15.         while (@a) {
  16.         my @output = ();
  17.                 for ( 1..4 ) {
  18.                         push @output, $b_param . shift @a;
  19.                         last unless @a;
  20.                 }
  21.         print join ($or_string, @output),"\n";
  22.         }
  23. print $tick;


« Previous Page