Sign In/My Account | View Cart  
advertisement


Listen Print

The Perl You Need To Know - Part 2
by Stas Bekman | Pages: 1, 2, 3

Another approach is to use fully qualified variables. This is better, since less memory will be used, but it adds a typing overhead:


  multirun2.pl
  -----------
  #!/usr/bin/perl -w

  use strict;

  for (1..3){
    print "run: [time $_]\n";
    run();
  }

  sub run {

    $main::counter = 0;

    increment_counter();
    increment_counter();

    sub increment_counter{
      $main::counter++;
      print "Counter is equal to $main::counter !\n";
    }

  } # end of sub run

You can also pass the variable to the subroutine by value and make the subroutine return it after it was updated. This adds time and memory overheads, so it may not be good idea if the variable can be very large, or if speed of execution is an issue.

Don't rely on the fact that the variable is small during the development of the application, it can grow quite big in situations you don't expect. For example, a simple HTML form text entry field can return a few megabytes of data if one of your users is bored and wants to test how good your code is. It's not uncommon to see users copy-and-paste 10Mb core dump files into a form's text fields and then submit it for your script to process.


  multirun3.pl
  -----------
  #!/usr/bin/perl -w

  use strict;

  for (1..3){
    print "run: [time $_]\n";
    run();
  }

  sub run {

    my $counter = 0;

    $counter = increment_counter($counter);
    $counter = increment_counter($counter);

    sub increment_counter{
      my $counter = shift;

      $counter++;
      print "Counter is equal to $counter !\n";

      return $counter;
    }

  } # end of sub run

Finally, you can use references to do the job. The version of increment_counter() below accepts a reference to the $counter variable and increments its value after first dereferencing it. When you use a reference, the variable you use inside the function is physically the same bit of memory as the one outside the function. This technique is often used to enable a called function to modify variables in a calling function.


  multirun4.pl
  -----------
  #!/usr/bin/perl -w

  use strict;

  for (1..3){
    print "run: [time $_]\n";
    run();
  }

  sub run {

    my $counter = 0;

    increment_counter(\$counter);
    increment_counter(\$counter);

    sub increment_counter{
      my $r_counter = shift;

      $$r_counter++;
      print "Counter is equal to $$r_counter !\n";
    }

  } # end of sub run

Here is yet another and more obscure reference usage. We modify the value of $counter inside the subroutine by using the fact that variables in @_ are aliases for the actual scalar parameters. Thus if you called a function with two arguments, then those would be stored in $_[0] and $_[1]. In particular, if an element $_[0] is updated, then the corresponding argument is updated (or an error occurs if it is not updatable as would be the case of calling the function with a literal, e.g. increment_counter(5)).


  multirun5.pl
  -----------
  #!/usr/bin/perl -w

  use strict;

  for (1..3){
    print "run: [time $_]\n";
    run();
  }

  sub run {

    my $counter = 0;

    increment_counter($counter);
    increment_counter($counter);

    sub increment_counter{
      $_[0]++;
      print "Counter is equal to $_[0] !\n";
    }

  } # end of sub run

The approach given above is generally not recommended because most Perl programmers will not expect $counter to be changed by the function; the example where we used \$counter, i.e. pass-by-reference would be preferred.

Here is a solution that avoids the problem entirely by splitting the code into two files: The first is really just a wrapper and loader, the second file contains the heart of the code.


  multirun6.pl
  -----------
  #!/usr/bin/perl -w

  use strict;
  require 'multirun6-lib.pl' ;

  for (1..3){
    print "run: [time $_]\n";
    run();
  }

Separate file:


  multirun6-lib.pl
  ----------------
  use strict ;

  my $counter;
  sub run {
    $counter = 0;
    increment_counter();
    increment_counter();
  }

  sub increment_counter{
    $counter++;
    print "Counter is equal to $counter !\n";
  }

  1 ;

Now you have at least six workarounds to choose from.

For more information, please refer to perlref and perlsub manpages.

Previously in the Series

The Perl You Need To Know

Installing mod_perl without superuser privileges

mod_perl in 30 minutes

Why mod_perl?

perldoc's Rarely Known But Very Useful Options

It's a known fact that one cannot become a Perl hacker and especially mod_perl hacker without knowing how to read Perl documentation and search through it. Books are good, but an easily accessible and searchable Perl reference at your fingertips is a great time saver. It always has the up-to-date information for the version of perl you're using.

Of course, you can use online Perl documentation at the Web. I prefer http://theoryx5.uwinnipeg.ca/CPAN/perl/ to the official URL: http://www.perl.com/pub/v/documentation is very slow :( . The perldoc utility provides you with access to the documentation installed on your system. To find out what Perl manpages are available execute:


  % perldoc perl

To find what functions perl has, execute:


  % perldoc perlfunc

To learn the syntax and to find examples of a specific function, you would execute (e.g. for open()):


  % perldoc -f open

Note: In perl5.005_03 and earlier, there is a bug in this and the -q options of perldoc. It won't call pod2man, but will display the section in POD format instead. Despite this bug it's still readable and very useful.

The Perl FAQ (perlfaq manpage) is in several sections. To search through the sections for open you would execute:


  % perldoc -q open

This will show you all the matching question-and-answer sections, still in POD format.

To read the perldoc manpage you would execute:


  % perldoc perldoc

References

  • Online documentation: http://theoryx5.uwinnipeg.ca/CPAN/perl/ http://www.perl.com/pub/v/documentation/

  • The book ``Programming Perl'' 3rd edition by L.Wall, T. Christiansen and J.Orwant (also known as the ``Camel'' book, named after the camel picture on the cover of the book). You want to refer to Chapter 8 that talks about nested subroutines among other things.

  • The perlref and perlsub man pages.