The 2003 Perl Advent Calendar
[about] | [archives] | [contact] | [home]

On the 19th day of Advent my True Language brought to me..
Acme::Code::FreedomFighter

Today is for most sensible people the last working day of the year before Christmas. It's a time to relax and be merry, so I won't bother you with the gritty details of any serious module, I'll instead bring you tales of yore from the depths of the Acme:: namespace.

If you've been paying attention the last few years you'll know that the Acme:: namespace is the black sheep of the CPAN collective, featuring modules that don't really have any practical purpose, other than to show some funky features of the language.

Are we sitting comfortably? Then I shall begin.

A long time ago (in a galaxy, far far away) - or on the 1987 if

  • perlhist
  • is to be believed - Larry released Perl 1. Sixteen years on and a day we've got a very different language.

    In this time what people want from the language has changed. For example, It used to be commonplace to use variables as soon as you wanted without declaring them first:

      $number = 42 * 4077 * 1701;
      print $numer;

    Of course, people soon got tired of making typos like the one above and decided that we should have the strict pragma. Amongst other things this enforces that you declare things before you use them. Like so:

      my $number = 42 * 4077 * 1701;
      print $numer;   # causes an error

    This explodes with a handy error telling us that $numer hasn't been predeclare (indeed, if you use diagnostics as we've seen previously you'll get a full explanation. This way perl doesn't silently create new variables whenever you make a typo (and hence produce hard to track down bugs) but complains right where the error is in your code there and then.

    People moaned. use strict allowed them to check what they were typing was correct, but also prevented them from abusing many of Perl's more powerful features. The argument goes that if you know what you're doing then you don't need to use strict. The counter argument goes that you should know when to turn it off.

      no strict;

    People claimed it was against the nature of the language to have to turn these things off. Other people insisted that you use strict at the start of the program.

  • holy wars
  • started. And then someone would suggest using vi over emacs (or vice versa,) and someone else would compare someone to Hitler, and to be frank that never helped the conversation.

    And then people would make

  • silly modules
  • based on mailing list posts by idiots who claimed in the worst possible way that use strict was not to be used. And other people countered with modules that turned
  • strict on everywhere
  • .

    In short, it got out of hand.

    Acme::Code::Police

    So eventually, whilst adding to the collection of goofball modules declared under the Acme:: namespace some bright spark came up with the idea of

  • Acme::Code::Police
  • . This module is insane. It consists of one line only

      INIT{unless(exists$INC{'strict.pm'}){unlink((caller)[1])}}

    This says, when someone loads the module unless someone has used use strict (i.e. it's been included in the %INC hash off all loaded modules) delete the file that contained the code that called us. Yes, that's right. This module deletes your source code! No recommended for commercial use!

    This makes use of two handy, yet not widely abused, functions of Perl. First, it looks in the %INC hash. The %INC hash contains the full path to all the modules that we've created (in Unix notation, no matter what platform.) For example:

      #!/usr/bin/perl
      # turn on perl's safety features
      use strict;
      use warnings;
      use Data::Dumper;
      print Dumper \%INC;

    prints out:

     $VAR1 = {
               'warnings/register.pm' => '/usr/share/perl/5.8.0/warnings/register.pm',
               'bytes.pm' => '/usr/share/perl/5.8.0/bytes.pm',
               'XSLoader.pm' => '/usr/lib/perl/5.8.0/XSLoader.pm',
               'Carp.pm' => '/usr/share/perl/5.8.0/Carp.pm',
               'Exporter.pm' => '/usr/share/perl/5.8.0/Exporter.pm',
               'strict.pm' => '/usr/share/perl/5.8.0/strict.pm',
               'warnings.pm' => '/usr/share/perl/5.8.0/warnings.pm',
               'overload.pm' => '/usr/share/perl/5.8.0/overload.pm',
               'Data/Dumper.pm' => '/usr/lib/perl/5.8.0/Data/Dumper.pm'
             };

    The Acme::Code::Police module uses this hash to determine if you've loaded strict at any point in your code or not.

    The other feature that Acme::Code::Police uses is the caller function. This can be used to find out various details about the code that called the current routine. For example:

      #!/usr/bin/perl
      # turn on perl's safety features
      use strict;
      use warnings;
      sub foo
      { 
         bar();
      }
      sub bar
      {
        print join ',', caller;
      }
      foo();

    This prints out:

      main, myscript.pl, 7

    Which is the package, filepath, and linenumber of what called bar. Acme::Code::Police uses this to work out the path to the file that called Acme::Code::Police without calling use strict first and deleted it.

    Acme::Code::FreedomFighter

    Acme::Code::FreedomFighter is a module that's designed to combat the nasty effects of Acme::Code::Police. Looking at the source of this module would make it immediately obvious how this functions, except for the fact that the author has used

  • Acme::Eyedrops
  • to convert the
  • source code
  • into a picture of Che Guevara. Go figure.

    Instead you'll have to guess what the source does, but I can tell you the effect. If you load it before Acme::Code::Police from your code then it's not the code that calls Acme::Code::Police that's getting deleted...but I'm not saying what else will

  • The lighter side of Perl article on perl.com